home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cfengine-1.5.3 / src / cfengine.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-20  |  119.3 KB  |  5,151 lines

  1. /* 
  2.  
  3.         Copyright (C) 1995
  4.         Free Software Foundation, Inc.
  5.  
  6.    This file is part of GNU cfengine - written and maintained 
  7.    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
  8.    Dept. of Theoretical physics, University of Oslo
  9.  
  10.    This program is free software; you can redistribute it and/or modify it
  11.    under the terms of the GNU General Public License as published by the
  12.    Free Software Foundation; either version 2, or (at your option) any
  13.    later version. 
  14.    This program is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.  
  19.   You should have received a copy of the GNU General Public License
  20.   along with this program; if not, write to the Free Software
  21.   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
  22.  
  23. */
  24.  
  25. /*******************************************************************/
  26. /*                                                                 */
  27. /*  Cfengine : a site configuration langugae                       */
  28. /*                                                                 */
  29. /*  Module: (main) cfengine.c                                      */
  30. /*                                                                 */
  31. /*  Mark Burgess 1994/96                                           */
  32. /*                                                                 */
  33. /*******************************************************************/
  34.  
  35. #define INET
  36.  
  37. #include "cf.defs.h"
  38. #include "cf.extern.h"
  39. #include "../pub/getopt.h"
  40.  
  41. /*******************************************************************/
  42. /* Level 0 : Main                                                  */
  43. /*******************************************************************/
  44.  
  45. main (argc,argv)
  46.  
  47. char *argv[];
  48. int argc;
  49.  
  50. { void HandleSignal();
  51.   struct Item *action;
  52.  
  53. signal (SIGTERM,HandleSignal);                   /* Signal Handler */
  54. signal (SIGHUP,HandleSignal);
  55. signal (SIGINT,HandleSignal);
  56. signal (SIGPIPE,HandleSignal);
  57.  
  58. Initialize(argc,argv);
  59.  
  60. if (! NOHARDCLASSES)
  61.    {
  62.    GetNameInfo();
  63.    }
  64.  
  65. PreNetConfig();
  66.  
  67. ReadRCFile(); /* Should come before parsing so that it can be overridden */
  68.  
  69. ParseInputFiles();
  70.  
  71. EchoValues();
  72.  
  73. if (PARSEONLY)                            /* Establish lock for root */
  74.    {
  75.    exit(0);
  76.    }
  77.  
  78. if (PRSYSADM)                                           /* -a option */
  79.    {
  80.    printf("%s\n",VSYSADM);
  81.    exit (0);
  82.    }
  83.  
  84.  
  85. openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_USER);
  86.  
  87. CheckSystemVariables();
  88.  
  89. for (action = VACTIONSEQ; action !=NULL; action=action->next)
  90.    {
  91.    Debug("Looking at action %s\n\n",action->name);
  92.    if (IsExcluded(action->classes))
  93.       {
  94.       continue;
  95.       }
  96.    
  97.    switch(EvaluateAction(action->name,&VADDCLASSES))
  98.       {
  99.       case mountinfo:
  100.                         GetHomeInfo();
  101.                         GetMountInfo();
  102.                         break;
  103.       case mkpaths:
  104.                         if (! NOFILECHECK)
  105.                            {
  106.                GetSetuidLog();
  107.                MakePaths();
  108.                SaveSetuidLog();
  109.                }
  110.                         break;
  111.       case lnks:
  112.                   if (!GetLock(ASUniqueName("link"),"all",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  113.                            {
  114.                            continue;
  115.                            }
  116.             
  117.                         MakeChildLinks();
  118.                         MakeLinks();
  119.             ReleaseCurrentLock();
  120.                         break;
  121.       case simplelnks:
  122.  
  123.                   if (!GetLock(ASUniqueName("link"),"simple",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  124.                            {
  125.                            continue;
  126.                            }
  127.       
  128.                         MakeLinks();
  129.             ReleaseCurrentLock();
  130.                         break;
  131.       case childlnks:
  132.  
  133.                   if (!GetLock(ASUniqueName("link"),"child",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  134.                            {
  135.                            continue;
  136.                            }
  137.             
  138.                         MakeChildLinks();
  139.             ReleaseCurrentLock();
  140.                         break;
  141.       case chkmail:
  142.             if (!GetLock("Mount",CanonifyName(VFSTAB[VSYSTEMHARDCLASS]),0,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  143.                {
  144.                return; /* Note IFELAPSED must be zero to avoid conflict with mountresc */
  145.                }
  146.       
  147.                         MailCheck();
  148.  
  149.             ReleaseCurrentLock();
  150.                         break;
  151.       case mountall:
  152.                         if (! NOMOUNTS )
  153.                            {
  154.                            MountFileSystems();
  155.                            }
  156.                         break;
  157.       case requir:
  158.                     if (!GetLock(ASUniqueName("disks"),"",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  159.                        {
  160.                continue;
  161.                }
  162.             CheckRequired();
  163.             ReleaseCurrentLock();
  164.             break;
  165.       case tidyf:
  166.                         if (! NOTIDY) 
  167.                            {
  168.                if (!GetLock(ASUniqueName("tidy"),"",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  169.                   {
  170.                   continue;
  171.                   }
  172.                
  173.                            TidyFiles();
  174.                ReleaseCurrentLock();
  175.                            }
  176.                         break;
  177.       case shellcom:
  178.                         if (! NOSCRIPTS)
  179.                            {
  180.                            Scripts();
  181.                            }
  182.                         break;
  183.       case chkfiles:
  184.                         if (! NOFILECHECK)
  185.                            {
  186.                if (!GetLock(ASUniqueName("files"),"",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  187.                   {
  188.                   continue;
  189.                   }
  190.                
  191.                            GetSetuidLog();
  192.                            CheckFiles();
  193.                            SaveSetuidLog();
  194.                ReleaseCurrentLock();
  195.                            }
  196.                         break;
  197.       case disabl:
  198.                   if (!GetLock(ASUniqueName("disable"),"",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  199.                            {
  200.                            continue;
  201.                            }
  202.             
  203.                         DisableFiles();
  204.             ReleaseCurrentLock();
  205.                         break;
  206.       case mountresc:
  207.                         if (! NOMOUNTS)
  208.                            {
  209.                if (!GetLock("Mountres",CanonifyName(VFSTAB[VSYSTEMHARDCLASS]),0,VEXPIREAFTER,VUQNAME,0))
  210.                   {
  211.                   return;    /* Note IFELAPSED must be zero to avoid conflict with mountresc */
  212.                   }
  213.  
  214.                Banner("Mount file system resources");
  215.                            MountHomeBinServers();
  216.                            MountMisc();
  217.                ReleaseCurrentLock();
  218.                            }
  219.                         break;
  220.       case umnt:
  221.                   if (!GetLock(ASUniqueName("unmount"),"",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  222.                            {
  223.                            continue;
  224.                            }
  225.             
  226.                         Unmount();
  227.             ReleaseCurrentLock();
  228.                         break;
  229.  
  230.       case edfil:
  231.                         if (! NOEDITS)
  232.                            {
  233.                            EditFiles();
  234.                            }
  235.                         break;
  236.  
  237.  
  238.       case resolv:
  239.  
  240.                     if (!GetLock(ASUniqueName("resolve"),"",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  241.                            {
  242.                            continue;
  243.                            }
  244.             
  245.                         CheckResolv();
  246.             ReleaseCurrentLock();
  247.                         break;
  248.       case imag:
  249.                         if (! NOCOPY)
  250.                            {
  251.                GetSetuidLog();
  252.                            MakeImages();
  253.                SaveSetuidLog();
  254.                            }
  255.                         break;
  256.       case netconfig:
  257.       
  258.             if (IFCONF)
  259.                {
  260.                ConfigureInterfaces();
  261.                }
  262.             
  263.                         break;
  264.  
  265.       case tzone:
  266.                         CheckTimeZone();
  267.                         break;
  268.  
  269.       case procs:
  270.                         if (! NOPROCS)
  271.                {
  272.                if (!GetLock(ASUniqueName("processes"),"",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  273.                   {
  274.                   continue;
  275.                   }
  276.                
  277.                CheckProcesses();
  278.                ReleaseCurrentLock();
  279.                }
  280.                         break;
  281.  
  282.       case plugin:      break;
  283.  
  284.       default:  
  285.                         sprintf(VBUFF,"Undefined action %s in sequence\n",action->name);
  286.                         FatalError(VBUFF);
  287.                         break;
  288.       }
  289.  
  290.    DeleteItemList(VADDCLASSES);
  291.    VADDCLASSES = NULL;
  292.    }
  293.  
  294. closelog();
  295. exit(0); 
  296. }
  297.  
  298. /*******************************************************************/
  299. /* Level 1                                                         */
  300. /*******************************************************************/
  301.  
  302. Initialize(argc,argv)
  303.  
  304. char *argv[];
  305. int argc;
  306.  
  307. { char *sp, *cfargv[maxargs];
  308.   int i, cfargc;
  309.   struct stat statbuf;
  310.   
  311. umask(0);                 /* This makes the DEFAULT modes absolute */
  312.  
  313. strcpy(VDOMAIN,CF_START_DOMAIN);
  314.  
  315. strcpy(VERSION,CFVERSION);
  316.  
  317. ISCFENGINE = true;
  318.  
  319. VFACULTY[0] = '\0';
  320. VSYSADM[0] = '\0';
  321. VNETMASK[0]= '\0';
  322. VBROADCAST[0] = '\0';
  323. VMAILSERVER[0] = '\0';
  324. VREPOSITORY[0] = '\0';
  325. VDEFAULTROUTE[0] = '\0';
  326. VARCH[0] = '\0';
  327.  
  328. ALLCLASSBUFFER[0] = '\0';
  329. CURRENTITEM[0] = '\0';
  330. GROUPBUFF[0] = '\0';
  331. ACTIONBUFF[0] = '\0';
  332. CURRENTPATH[0] = '\0';
  333. CLASSBUFF[0] = '\0';
  334. LINKFROM[0] = '\0';
  335.  
  336. #ifndef HAVE_REGCOMP
  337. re_syntax_options |= RE_INTERVALS;
  338. #endif
  339.  
  340. strcpy(VINPUTFILE,"cfengine.conf");
  341. strcpy(VNFSTYPE,"nfs");
  342.  
  343. InitHashTable();
  344.  
  345. AddClassToHeap("any");      /* This is a reserved word / wildcard */
  346.  
  347. if (stat("/etc/debian_version",&statbuf) != -1)
  348.    {
  349.    Verbose("\nThis appears to be a debian system.\n");
  350.    AddClassToHeap("debian");
  351.    }
  352.  
  353. if (stat("/usr/src/redhat",&statbuf) != -1)
  354.    {
  355.    Verbose("This appears to be a redhat system.\n");
  356.    AddClassToHeap("redhat");
  357.    }
  358.  
  359. /* Note we need to fix the options since the argv mechanism doesn't */
  360.  /* work when the shell #!/bla/cfengine -v -f notation is used.      */
  361.  /* Everything ends up inside a single argument! Here's the fix      */
  362.  
  363. cfargc = 1;
  364. cfargv[0]="cfengine";
  365.  
  366. for (i = 1; i < argc; i++)
  367.    {
  368.    sp = argv[i];
  369.  
  370.    while (*sp != '\0')
  371.       {
  372.       while (*sp == ' ' && *sp != '\0') /* Skip to arg */
  373.          {
  374.      if (*sp == ' ')
  375.         {
  376.         *sp = '\0'; /* Break argv string */
  377.         }
  378.      sp++;
  379.          }
  380.  
  381.       cfargv[cfargc++] = sp;
  382.       
  383.       while (*sp != ' ' && *sp != '\0') /* Skip to white space */
  384.          {
  385.      sp++;
  386.          }
  387.       }
  388.    }
  389.  
  390. VDEFAULTBINSERVER.name = "";
  391.  
  392. VEXPIREAFTER = VDEFAULTEXPIREAFTER;
  393. VIFELAPSED = VDEFAULTIFELAPSED;
  394.  
  395. CheckOpts(cfargc,cfargv);
  396. }
  397.  
  398. /*******************************************************************/
  399.  
  400. PreNetConfig()                           /* Execute a shell script */
  401.  
  402. { struct stat buf;
  403.   char comm[bufsize];
  404.   char *sp;
  405.   FILE *pp;
  406.  
  407. if (NOPRECONFIG)
  408.    {
  409.    CfLog(cfverbose,"Ignoring the cf.preconf file: option set","");
  410.    return;
  411.    }
  412.  
  413. if ((sp=getenv(CFINPUTSVAR)) != NULL)
  414.    {
  415.    sprintf(comm,"%s/%s",sp,VPRECONFIG);
  416.  
  417.    if (stat(comm,&buf) == -1)
  418.        {
  419.        CfLog(cfverbose,"No preconfiguration file","");
  420.        return;
  421.        }
  422.    
  423.    sprintf(comm,"%s/%s %s 2>&1",sp,VPRECONFIG,CLASSTEXT[VSYSTEMHARDCLASS]);
  424.    }
  425. else
  426.    {
  427.    sprintf(comm,"./%s",VPRECONFIG);
  428.  
  429.    if (stat(comm,&buf) == -1)
  430.        {
  431.        CfLog(cfverbose,"No preconfiguration file\n","");
  432.        return;
  433.        }
  434.       
  435.    sprintf(comm,"./%s %s",VPRECONFIG,CLASSTEXT[VSYSTEMHARDCLASS]);
  436.    }
  437.  
  438. if (S_ISDIR(buf.st_mode) || S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode))
  439.    {
  440.    sprintf(OUTPUT,"Error: %s was not a regular file\n",VPRECONFIG);
  441.    CfLog(cferror,OUTPUT,"");
  442.    FatalError("Aborting.");
  443.    }
  444.  
  445. Verbose("\n\nExecuting Net Preconfiguration script...%s\n\n",VPRECONFIG);
  446.  
  447. if ((pp = cfpopen(comm,"r")) == NULL)
  448.    {
  449.    sprintf(OUTPUT,"Failed to open pipe to %s\n",comm);
  450.    CfLog(cferror,OUTPUT,"");
  451.    return;
  452.    }
  453.  
  454. while (!feof(pp))
  455.    {
  456.    if (ferror(pp))  /* abortable */
  457.       {
  458.       CfLog(cferror,"Error running preconfig\n","ferror");
  459.       break;
  460.       }
  461.  
  462.    ReadLine(VBUFF,bufsize,pp);
  463.  
  464.    if (feof(pp))
  465.       {
  466.       break;
  467.       }
  468.    
  469.    if (ferror(pp))  /* abortable */
  470.       {
  471.       CfLog(cferror,"Error running preconfig\n","ferror");
  472.       break;
  473.       }
  474.  
  475.    CfLog(cfinform,VBUFF,"");
  476.    }
  477.  
  478. cfpclose(pp);
  479. }
  480.  
  481. /*******************************************************************/
  482.  
  483. ReadRCFile()
  484.  
  485. { char filename[bufsize], buffer[bufsize], *sp, *mp;
  486.   char class[maxvarsize], variable[maxvarsize], value[maxvarsize];
  487.   int c;
  488.   FILE *fp;
  489.  
  490. filename[0] = buffer[0] = class[0] = variable[0] = value[0] = '\0';
  491. LINENUMBER = 0;
  492.  
  493. if ((sp=getenv(CFINPUTSVAR)) != NULL)
  494.    {
  495.    strcpy(filename,sp);
  496.    if (filename[strlen(filename)-1] != '/')
  497.       {
  498.       strcat(filename,"/");
  499.       }
  500.    }
  501.  
  502. strcat(filename,VRCFILE);
  503.  
  504. if ((fp = fopen(filename,"r")) == NULL)      /* Open root file */
  505.    {
  506.    return;
  507.    }
  508.  
  509. while (!feof(fp))
  510.    {
  511.    ReadLine(buffer,bufsize,fp);
  512.    LINENUMBER++;
  513.    class[0]='\0';
  514.    variable[0]='\0';
  515.    value[0]='\0';
  516.  
  517.    if (strlen(buffer) == 0 || buffer[0] == '#')
  518.       {
  519.       continue;
  520.       }
  521.  
  522.    if (strstr(buffer,":") == 0)
  523.       {
  524.       sprintf(OUTPUT,"Malformed line (missing :) in resource file %s - skipping\n",VRCFILE);
  525.       CfLog(cferror,OUTPUT,"");
  526.       continue;
  527.       }
  528.  
  529.    sscanf(buffer,"%[^.].%[^:]:%[^\n]",class,variable,value);
  530.  
  531.    if (class[0] == '\0' || variable[0] == '\0' || value[0] == '\0')
  532.       {
  533.       sprintf(OUTPUT,"%s:%s - Bad resource\n",VRCFILE,buffer);
  534.       CfLog(cferror,OUTPUT,"");
  535.       sprintf(OUTPUT,"class=%s,variable=%s,value=%s\n",class,variable,value);
  536.       CfLog(cferror,OUTPUT,"");
  537.       FatalError("Bad resource");
  538.       }
  539.  
  540.    if (strcmp(CLASSTEXT[VSYSTEMHARDCLASS],class) != 0) 
  541.       {
  542.       continue;  /* No point if not equal*/
  543.       }
  544.  
  545.    if ((mp = strdup(value)) == NULL)
  546.       {
  547.       perror("malloc");
  548.       FatalError("malloc in ReadRCFile");
  549.       }
  550.  
  551.    sprintf(OUTPUT,"Redefining resource %s as %s (%s)\n",variable,value,class);
  552.    CfLog(cfverbose,OUTPUT,"");
  553.  
  554.    c = VSYSTEMHARDCLASS;
  555.  
  556.    switch (GetResource(variable))
  557.       {
  558.       case rmountcom:
  559.                         VMOUNTCOMM[c] = mp;
  560.                         break;
  561.  
  562.       case runmountcom:
  563.                         VUNMOUNTCOMM[c] = mp;
  564.                         break;
  565.       case rethernet:
  566.                         VIFDEV[c] = mp;
  567.                         break;
  568.       case rmountopts:
  569.                         VMOUNTOPTS[c] = mp;
  570.                         break;
  571.       case rfstab:
  572.                         VFSTAB[c] = mp;
  573.                         break;
  574.       case rmaildir:
  575.                         VMAILDIR[c] = mp;
  576.                         break;
  577.       case rnetstat:
  578.                         VNETSTAT[c] = mp;
  579.                         break;
  580.       case rpscomm:
  581.                     VPSCOMM[c] = mp;
  582.                     break;
  583.       case rpsopts:
  584.                     VPSOPTS[c] = mp;
  585.                     break;
  586.       default:
  587.                         sprintf(VBUFF,"Bad resource %s in %s\n",variable,VRCFILE);
  588.                         FatalError(VBUFF);
  589.                         break;
  590.       }
  591.    }
  592.  
  593. fclose(fp);
  594. }
  595.  
  596. /*******************************************************************/
  597.  
  598. EchoValues()
  599.  
  600. { struct Item *ip;
  601.   int n = 0;
  602.   
  603. if (strstr(VSYSNAME.nodename,ToLowerStr(VDOMAIN)))
  604.    {
  605.    strcpy(VFQNAME,VSYSNAME.nodename);
  606.    
  607.    while(VSYSNAME.nodename[n++] != '.')
  608.       {
  609.       }
  610.    
  611.    strncpy(VUQNAME,VSYSNAME.nodename,n-1);
  612.    }
  613. else
  614.    {
  615.    sprintf(VFQNAME,"%s.%s",VSYSNAME.nodename,ToLowerStr(VDOMAIN));
  616.    strcpy(VUQNAME,VSYSNAME.nodename);
  617.    }
  618.  
  619. Verbose("Accepted domain name: %s\n\n",VDOMAIN); 
  620. bzero(VBUFF,bufsize);
  621.  
  622. if (GetMacroValue("OutputPrefix"))
  623.    {
  624.    ExpandVarstring("$(OutputPrefix)",VBUFF,NULL);
  625.    }
  626.  
  627. if (strlen(VBUFF) != 0)
  628.    {
  629.    strncpy(VPREFIX,VBUFF,40);  /* No more than 40 char prefix (!) */
  630.    }
  631. else
  632.    {
  633.    strcpy(VPREFIX,"cfengine:");
  634.    strcat(VPREFIX,VUQNAME);
  635.    }
  636.  
  637.  
  638. sprintf(LOGFILE,"%s/cfengine.%s.log",LOGFILEDIR,VUQNAME);
  639.  
  640. strcpy(VSETUIDLOG,LOGFILE);
  641.  
  642. if (VERBOSE || DEBUG || D2 || D3)
  643.    {
  644.    struct Item *ip;
  645.    
  646.    ListDefinedClasses();
  647.  
  648.    printf("\nGlobal expiry time for locks: %d minutes\n",VEXPIREAFTER);
  649.    printf("\nGlobal anti-spam elapse time: %d minutes\n\n",VIFELAPSED);
  650.  
  651.    printf("Extensions which should not be directories = ( ");
  652.    for (ip = EXTENSIONLIST; ip != NULL; ip=ip->next)
  653.       {
  654.       printf("%s ",ip->name);
  655.       }
  656.    printf(")\n");
  657.  
  658.    printf("Suspicious filenames to be warned about = ( ");
  659.    for (ip = SUSPICIOUSLIST; ip != NULL; ip=ip->next)
  660.       {
  661.       printf("%s ",ip->name);
  662.       }
  663.    printf(")\n");
  664.    
  665.    }
  666.  
  667. if (DEBUG || D2 || D3)
  668.    {
  669.    printf("\nFully qualified hostname is: %s\n",VFQNAME);
  670.    printf("Unqualified hostname is: %s\n",VUQNAME);
  671.    printf("\nSystem administrator mail address is: %s\n",VSYSADM);
  672.    printf("Sensible size = %d\n",SENSIBLEFSSIZE);
  673.    printf("Sensible count = %d\n",SENSIBLEFILECOUNT);
  674.    printf("Edit File (Max) Size = %d\n\n",EDITFILESIZE);
  675.    printf("------------------------------------------------------------\n");
  676.    ListDefinedInterfaces();
  677.    printf("------------------------------------------------------------\n");
  678.    ListDefinedBinservers();
  679.    printf("------------------------------------------------------------\n");
  680.    ListDefinedHomeservers();
  681.    printf("------------------------------------------------------------\n");
  682.    ListDefinedHomePatterns();
  683.    printf("------------------------------------------------------------\n");
  684.    ListActionSequence();
  685.  
  686.    printf("\nWill need to copy from the following trusted sources = ( ");
  687.  
  688.    for (ip = VSERVERLIST; ip !=NULL; ip=ip->next)
  689.       {
  690.       printf("%s ",ip->name);
  691.       }
  692.    printf(")\n");
  693.    printf("\nUsing mailserver %s\n",VMAILSERVER);
  694.    printf("\nLocal mountpoints: ");
  695.    for (ip = VMOUNTLIST; ip != NULL; ip=ip->next)
  696.       {
  697.       printf ("%s ",ip->name);
  698.       }
  699.    printf("\n");
  700.    printf("\nDefault route for packets %s\n\n",VDEFAULTROUTE);
  701.    printf("\nFile repository = %s\n\n",VREPOSITORY);
  702.    printf("\nNet interface name = %s\n",VIFDEV[VSYSTEMHARDCLASS]);
  703.    printf("------------------------------------------------------------\n");
  704.    ListDefinedResolvers();
  705.    printf("------------------------------------------------------------\n");
  706.    ListDefinedRequired();
  707.    printf("------------------------------------------------------------\n");
  708.    ListDefinedMountables();
  709.    printf("------------------------------------------------------------\n");
  710.    ListMiscMounts();
  711.    printf("------------------------------------------------------------\n");
  712.    ListUnmounts();
  713.    printf("------------------------------------------------------------\n");
  714.    ListDefinedMakePaths();
  715.    printf("------------------------------------------------------------\n");
  716.    ListDefinedImports();
  717.    printf("------------------------------------------------------------\n");
  718.    ListFiles();
  719.    printf("------------------------------------------------------------\n");
  720.    ListACLs();
  721.    printf("------------------------------------------------------------\n");
  722.    ListDefinedIgnore();
  723.    printf("------------------------------------------------------------\n");
  724.    ListFileEdits();
  725.    printf("------------------------------------------------------------\n");
  726.    ListProcesses();
  727.    printf("------------------------------------------------------------\n");
  728.    ListDefinedImages();
  729.    printf("------------------------------------------------------------\n");
  730.    ListDefinedTidy();
  731.    printf("------------------------------------------------------------\n");
  732.    ListDefinedDisable();
  733.    printf("------------------------------------------------------------\n");
  734.    ListDefinedLinks();
  735.    printf("------------------------------------------------------------\n");
  736.    ListDefinedLinkchs();
  737.    printf("------------------------------------------------------------\n");
  738.    ListDefinedScripts();
  739.    printf("------------------------------------------------------------\n");
  740.  
  741.    
  742.    if (IGNORELOCK)
  743.       {
  744.       printf("\nIgnoring locks...\n");
  745.       }
  746.    }
  747. }
  748.  
  749. /*******************************************************************/
  750.  
  751. CheckSystemVariables()
  752.  
  753. { char id[maxvarsize];
  754.   struct stat statbuf; 
  755.   int time, hash, activecfs, locks;
  756.   char *sp;
  757.  
  758. Debug2("\n\n");
  759.  
  760. if (VACTIONSEQ == NULL)
  761.    {
  762.    Warning("actionsequence is empty ");
  763.    Warning("perhaps cfengine.conf has not yet been set up?");
  764.    }
  765.  
  766. sprintf(id,"%d",geteuid());   /* get effective user id */
  767.  
  768. if (VACCESSLIST != NULL && !IsItemIn(VACCESSLIST,id))
  769.    {
  770.    FatalError("Access denied");
  771.    }
  772.  
  773. Debug2("cfengine -d : Debugging output enabled.\n");
  774.  
  775. if (DONTDO && (VERBOSE || DEBUG || D2))
  776.    {
  777.    printf("cfengine -n: Running in ``All talk and no action'' mode\n");
  778.    }
  779.  
  780. if (TRAVLINKS && (VERBOSE || DEBUG || D2))
  781.    {
  782.    printf("cfengine -l : will traverse symbolic links\n");
  783.    }
  784.  
  785. if ( ! IFCONF && (VERBOSE || DEBUG || D2))
  786.    {
  787.    printf("cfengine -i : suppressing interface configuration\n");
  788.    }
  789.  
  790. if ( NOFILECHECK && (VERBOSE || DEBUG || D2))
  791.    {
  792.    printf("cfengine -c : suppressing file checks\n");
  793.    }
  794.  
  795. if ( NOSCRIPTS && (VERBOSE || DEBUG || D2))
  796.    {
  797.    printf("cfengine -s : suppressing script execution\n");
  798.    }
  799.  
  800. if ( NOTIDY && (VERBOSE || DEBUG || D2))
  801.    {
  802.    printf("cfengine -t : suppressing tidy function\n");
  803.    }
  804.  
  805. if ( NOMOUNTS && (VERBOSE || DEBUG || D2))
  806.    {
  807.    printf("cfengine -m : suppressing mount operations\n");
  808.    }
  809.  
  810. if ( MOUNTCHECK && (VERBOSE || DEBUG || D2))
  811.    {
  812.    printf("cfengine -C : check mount points\n");
  813.    }
  814.  
  815.  
  816. if (ERRORCOUNT > 0)
  817.    {
  818.    FatalError("Execution terminated after parsing due to errors in program");
  819.    }
  820.  
  821. strcpy(VCANONICALFILE,CanonifyName(VINPUTFILE));
  822.  
  823. if (GetMacroValue("LockDirectory"))
  824.    {
  825.    strcpy(VLOCKDIR,GetMacroValue("LockDirectory"));
  826.    }
  827.  
  828.  if (GetMacroValue("LogDirectory"))
  829.    {
  830.    strcpy(VLOGDIR,GetMacroValue("LogDirectory"));
  831.    }
  832.  
  833. if (getuid() != 0)
  834.    {
  835.    Verbose("\n(Not root user...)\n\n");
  836.    
  837.    if ((sp = getenv("HOME")) == NULL)
  838.       {
  839.       FatalError("You do not have a HOME variable pointing to your home directory");
  840.       }
  841.  
  842.    sprintf(VLOGDIR,"%s/.cfengine",sp);
  843.    sprintf(VLOCKDIR,"%s/.cfengine",sp);
  844.  
  845.    sprintf(VBUFF,"%s/.cfengine/test",sp);
  846.    MakeDirectoriesFor(VBUFF);
  847.    }
  848. else
  849.    {
  850.    strcpy(VLOGDIR,LOGFILEDIR);
  851.    strcpy(VLOCKDIR,LOCKFILEDIR);
  852.  
  853.    sprintf(VBUFF,"%s/test",LOCKFILEDIR);
  854.    MakeDirectoriesFor(VBUFF);
  855.    sprintf(VBUFF,"%s/test",LOGFILEDIR);
  856.    MakeDirectoriesFor(VBUFF);
  857.    }
  858.  
  859. if (stat(VLOCKDIR,&statbuf) == -1)
  860.    {
  861.    if (statbuf.st_mode & 07)
  862.       {
  863.       CfLog(cferror,"Lock directory %s is not private! Mode %o\n",VLOCKDIR);
  864.       }
  865.    }
  866.  
  867. chmod(VLOCKDIR,(mode_t)0700); /* Locks must be immutable to others */
  868.  
  869. LoadSecretKeys();
  870.  
  871. if (GetMacroValue("MaxCfengines"))
  872.    {
  873.    activecfs = atoi(GetMacroValue("MaxCfengines"));
  874.    locks = CountActiveLocks();
  875.    
  876.    if (locks >= activecfs)
  877.       {
  878.       sprintf(OUTPUT,"Too many cfengines running (%d/%d)\n",locks,activecfs);
  879.       CfLog(cferror,OUTPUT,"");
  880.       closelog();
  881.       exit(1);
  882.       }
  883.    }
  884.  
  885. if (GetMacroValue("Verbose") && (strcmp(GetMacroValue("Verbose"),"on") == 0))
  886.    {
  887.    VERBOSE = true;
  888.    }
  889.  
  890. if (GetMacroValue("Inform") && (strcmp(GetMacroValue("Inform"),"on") == 0))
  891.    {
  892.    INFORM = true;
  893.    } 
  894.  
  895. INFORM_save = INFORM;
  896.  
  897. if (GetMacroValue("Syslog") && (strcmp(GetMacroValue("Syslog"),"on") == 0))
  898.    {
  899.    LOGGING = true;
  900.    }
  901.  
  902. LOGGING_save = LOGGING;
  903.  
  904. if (GetMacroValue("DryRun") && (strcmp(GetMacroValue("DryRun"),"on") == 0))
  905.    {
  906.    DONTDO = true;
  907.    }
  908.  
  909. if (GetMacroValue("Warnings") && (strcmp(GetMacroValue("Warnings"),"on") == 0))
  910.    {
  911.    WARNINGS = true;
  912.    }
  913.  
  914. if (GetMacroValue("NonAlphaNumFiles") && (strcmp(GetMacroValue("NonAlphaNumFiles"),"on") == 0))
  915.    {
  916.    NONALPHAFILES = true;
  917.    }
  918.  
  919. if (GetMacroValue("SecureInput") && (strcmp(GetMacroValue("SecureInput"),"on") == 0))
  920.    {
  921.    CFPARANOID = true;
  922.    }
  923.  
  924. if (GetMacroValue("ShowActions") && (strcmp(GetMacroValue("ShowActions"),"on") == 0))
  925.    {
  926.    SHOWACTIONS = true;
  927.    }
  928.  
  929. bzero(CHECKSUMDB,bufsize);
  930.  
  931. if (GetMacroValue("ChecksumDatabase"))
  932.    {
  933.    ExpandVarstring("$(ChecksumDatabase)",CHECKSUMDB,NULL);
  934.  
  935.    if (*CHECKSUMDB != '/')
  936.       {
  937.       FatalError("$(ChecksumDatabase) does not expand to an absolute filename\n");
  938.       }
  939.    }
  940.  
  941. if (GetMacroValue("ChecksumUpdates") && (strcmp(GetMacroValue("ChecksumUpdates"),"on") == 0))
  942.    {
  943.    CHECKSUMUPDATES = true;
  944.    } 
  945.  
  946. if (GetMacroValue("TimeOut"))
  947.    {
  948.    time = atoi(GetMacroValue("TimeOut"));
  949.  
  950.    if (time < 3 || time > 60)
  951.       {
  952.       CfLog(cfinform,"TimeOut not between 3 and 60 seconds, ignoring.\n","");
  953.       }
  954.    else
  955.       {
  956.       CF_TIMEOUT = time;
  957.       }
  958.    }
  959.  
  960.  if (NOSPLAY)
  961.    {
  962.    return;
  963.    }
  964.  
  965. time = 0;
  966. hash = Hash(VFQNAME);
  967.  
  968. if (GetMacroValue("SplayTime"))
  969.    {
  970.    time = atoi(GetMacroValue("SplayTime"));
  971.  
  972.    if (time < 0)
  973.       {
  974.       CfLog(cfinform,"SplayTime with negative value, ignoring.\n","");
  975.       return;
  976.       }
  977.  
  978.    sprintf(OUTPUT,"Sleeping for SplayTime %d seconds\n\n",(int)(time*60*hash/hashtablesize));
  979.    CfLog(cfverbose,OUTPUT,"");
  980.    sleep((int)(time*60*hash/hashtablesize));
  981.    }
  982.  
  983. }
  984.  
  985. /*******************************************************************/
  986.  
  987. enum aseq EvaluateAction(action,classlist)
  988.  
  989. char *action;
  990. struct Item **classlist;
  991.  
  992. { int i,j = 0;
  993.   char *sp,cbuff[bufsize],actiontxt[bufsize];
  994.   struct Item *ip;
  995.  
  996. cbuff[0]='\0';
  997. actiontxt[0]='\0';
  998. sp = action;
  999.  
  1000. while (*sp != '\0')
  1001.    {
  1002.    ++j;
  1003.    sscanf(sp,"%[^.]",cbuff);
  1004.  
  1005.    while ((*sp != '\0') && (*sp !='.'))
  1006.       {
  1007.       sp++;
  1008.       }
  1009.  
  1010.    if (*sp == '.')
  1011.       {
  1012.       sp++;
  1013.       }
  1014.  
  1015.    if (IsHardClass(cbuff))
  1016.       {
  1017.       sprintf(OUTPUT,"Error in action sequence: %s\n",action);
  1018.       CfLog(cferror,OUTPUT);
  1019.       FatalError("You cannot add a reserved class!");
  1020.       }
  1021.  
  1022.    if (j == 1)
  1023.       {
  1024.       VIFELAPSED = VDEFAULTIFELAPSED;
  1025.       VEXPIREAFTER = VDEFAULTEXPIREAFTER;
  1026.       strcpy(actiontxt,cbuff);
  1027.       continue;
  1028.       }
  1029.    else
  1030.       {
  1031.       if ((strncmp(actiontxt,"module:",7) != 0) && ! IsSpecialClass(cbuff))
  1032.      {
  1033.          AppendItem(classlist,cbuff,NULL);
  1034.      }
  1035.       }
  1036.    }
  1037.  
  1038.  
  1039. BuildClassEnvironment();
  1040.  
  1041. if ((VERBOSE || DEBUG || D2) && *classlist != NULL)
  1042.    {
  1043.    printf("\n                  New temporary class additions\n");
  1044.    printf("                  -----------------------------\n");
  1045.    for (ip = *classlist; ip != NULL; ip=ip->next)
  1046.       {
  1047.       printf("                             %s\n",ip->name);
  1048.       }
  1049.    }
  1050.  
  1051. for (i = 0; ACTIONSEQTEXT[i] != NULL; i++)
  1052.    {
  1053.    if (strcmp(ACTIONSEQTEXT[i],actiontxt) == 0)
  1054.       {
  1055.       return (enum aseq) i;
  1056.       }
  1057.    }
  1058.  
  1059. if (strncmp(actiontxt,"module:",7) == 0)
  1060.    {
  1061.    CheckForModule(actiontxt);
  1062.    return plugin;
  1063.    }
  1064.  
  1065. return(non);
  1066. }
  1067.  
  1068. /*******************************************************************/
  1069.  
  1070. GetHomeInfo()
  1071.  
  1072. { DIR *dirh;
  1073.   struct dirent *dirp;
  1074.   struct Item *ip;
  1075.  
  1076. if (getuid() != 0)                            
  1077.    {
  1078.    Debug("Not root, so skipping GetHomeInfo()\n");
  1079.    return;
  1080.    }
  1081.  
  1082. if (!MountPathDefined())
  1083.    {
  1084.    return;
  1085.    }
  1086.  
  1087.  
  1088. for (ip = VMOUNTLIST; ip != NULL; ip=ip->next)
  1089.    {
  1090.    if (IsExcluded(ip->classes))
  1091.       {
  1092.       continue;
  1093.       }
  1094.    
  1095.    if ((dirh = opendir(ip->name)) == NULL)
  1096.       {
  1097.       sprintf(OUTPUT,"INFO: Host %s seems to have no (additional) local disks except the OS\n",VDEFAULTBINSERVER.name);
  1098.       CfLog(cfverbose,OUTPUT,"");
  1099.       sprintf(OUTPUT,"      mounted under %s\n\n",ip->name);
  1100.       CfLog(cfverbose,OUTPUT,"");
  1101.       return;
  1102.       }
  1103.  
  1104.    for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
  1105.       {
  1106.       if (!SensibleFile(dirp->d_name,ip->name,NULL))
  1107.          {
  1108.          continue;
  1109.          }
  1110.  
  1111.       strcpy(VBUFF,ip->name);
  1112.       AddSlash(VBUFF);
  1113.       strcat(VBUFF,dirp->d_name);
  1114.  
  1115.       if (IsHomeDir(VBUFF))
  1116.          {
  1117.          sprintf(OUTPUT,"Host defines a home directory %s\n",VBUFF);
  1118.      CfLog(cfverbose,OUTPUT,"");
  1119.          }
  1120.       else
  1121.          {
  1122.          sprintf(OUTPUT,"Host defines a potential mount point %s\n",VBUFF);
  1123.      CfLog(cfverbose,OUTPUT,"");
  1124.          }
  1125.  
  1126.       sprintf(CURRENTPATH,"%s%s",ip->name,dirp->d_name);
  1127.       sprintf(CURRENTITEM,"%s:%s",VDEFAULTBINSERVER.name,CURRENTPATH);
  1128.  
  1129.       if (! IsItemIn(VMOUNTED,CURRENTITEM))
  1130.          {
  1131.          if ( MOUNTCHECK && ! RequiredFileSystemOkay(CURRENTPATH) && VERBOSE)
  1132.             {
  1133.             sprintf(OUTPUT,"Found a mountpoint %s but there was\n",CURRENTPATH);
  1134.         CfLog(cfinform,OUTPUT,"");
  1135.             CfLog(cfinform,"nothing mounted on it.\n\n","");
  1136.             }
  1137.          }
  1138.       }
  1139.    closedir(dirh);
  1140.    }
  1141. }
  1142.  
  1143. /*******************************************************************/
  1144.  
  1145. GetMountInfo ()  /* This is, in fact, the most portable way to read the mount info! */
  1146.                  /* Depressing, isn't it? */
  1147. { FILE *pp;
  1148.   struct Item *mp;
  1149.   char buf1[bufsize],buf2[bufsize],buf3[bufsize];
  1150.   char host[maxvarsize], mounton[bufsize];
  1151.   int i, TimeOut();
  1152.  
  1153. if (!GetLock(ASUniqueName("mountinfo"),"",0,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  1154.    {
  1155.    return;
  1156.    }
  1157.  
  1158. Banner("Building list of currently mounted filesystems");
  1159.  
  1160.   /* sscanf(VMOUNTCOMM[VSYSTEMHARDCLASS],"%s",buf1); */
  1161.   /* Old BSD scanf crashes here! Why!? workaround: */
  1162.  
  1163. for (i=0; VMOUNTCOMM[VSYSTEMHARDCLASS][i] != ' '; i++)
  1164.    {
  1165.    buf1[i] =  VMOUNTCOMM[VSYSTEMHARDCLASS][i];
  1166.    }
  1167.  
  1168. buf1[i] = '\0';
  1169.  
  1170. signal(SIGALRM,(void *)TimeOut);
  1171. alarm(RPCTIMEOUT);
  1172.  
  1173. if ((pp = cfpopen(buf1,"r")) == NULL)
  1174.    {
  1175.    sprintf(OUTPUT,"%s: Can't open %s\n",VPREFIX,buf1);
  1176.    CfLog(cferror,OUTPUT,"popen");
  1177.    return;
  1178.    }
  1179.  
  1180. do
  1181.    {
  1182.    VBUFF[0] = buf1[0] = buf2[0] = buf3[0] = '\0';
  1183.  
  1184.    if (ferror(pp))  /* abortable */
  1185.       {
  1186.       GOTMOUNTINFO = false;
  1187.       CfLog(cferror,"Error getting mount info\n","ferror");
  1188.       break;
  1189.       }
  1190.    
  1191.    ReadLine(VBUFF,bufsize,pp);
  1192.  
  1193.    if (ferror(pp))  /* abortable */
  1194.       {
  1195.       GOTMOUNTINFO = false;
  1196.       CfLog(cferror,"Error getting mount info\n","ferror");
  1197.       break;
  1198.       }
  1199.    
  1200.    sscanf(VBUFF,"%s%s%s",buf1,buf2,buf3);
  1201.  
  1202.    if (VBUFF[0] == '\n')
  1203.       {
  1204.       break;
  1205.       }
  1206.  
  1207.    if (strstr(VBUFF,"not responding"))
  1208.       {
  1209.       printf("%s: %s\n",VPREFIX,VBUFF);
  1210.       }
  1211.  
  1212.    if (strstr(VBUFF,"be root"))
  1213.       {
  1214.       CfLog(cferror,"Mount access is denied. You must be root.\n","");
  1215.       CfLog(cferror,"Use the -n option to run safely.","");
  1216.       }
  1217.  
  1218.    if (strstr(VBUFF,"retrying") || strstr(VBUFF,"denied") || strstr(VBUFF,"backgrounding"))
  1219.       {
  1220.       continue;
  1221.       }
  1222.  
  1223.    if (strstr(VBUFF,"exceeded") || strstr(VBUFF,"busy"))
  1224.       {
  1225.       continue;
  1226.       }
  1227.  
  1228.    if (strstr(VBUFF,"RPC"))
  1229.       {
  1230.       if (! SILENT)
  1231.          {
  1232.          CfLog(cfinform,"There was an RPC timeout. Aborting mount operations.\n","");
  1233.          CfLog(cfinform,"Session failed while trying to talk to remote host\n","");
  1234.          sprintf(OUTPUT,"%s\n",VBUFF);
  1235.      CfLog(cfinform,OUTPUT);
  1236.          }
  1237.  
  1238.       GOTMOUNTINFO = false;
  1239.       ReleaseCurrentLock();
  1240.       cfpclose(pp);
  1241.       return;
  1242.       }
  1243.  
  1244.    switch (VSYSTEMHARDCLASS)
  1245.       {
  1246.       case sun4:
  1247.       case sun3:
  1248.       case ultrx: 
  1249.       case irix:
  1250.       case irix4:
  1251.       case irix64:
  1252.       case linuxx:
  1253.       case GnU:
  1254.       case unix_sv:
  1255.       case freebsd:
  1256.       case netbsd:
  1257.       case openbsd:
  1258.       case bsd_i:
  1259.       case nextstep:
  1260.       case bsd4_3:
  1261.       case newsos:
  1262.       case aos:
  1263.       case osf:
  1264.       case crayos:
  1265.                     if (buf1[0] == '/')
  1266.                        {
  1267.                        strcpy(host,VDEFAULTBINSERVER.name);
  1268.                        strcpy(mounton,buf3);
  1269.                        }
  1270.                     else
  1271.                        {
  1272.                        sscanf(buf1,"%[^:]",host);
  1273.                        strcpy(mounton,buf3);
  1274.                        }
  1275.  
  1276.                     break;
  1277.       case solaris:
  1278.       case solarisx86:
  1279.       case hp10:
  1280.       case hp:      
  1281.                     if (buf3[0] == '/')
  1282.                        {
  1283.                        strcpy(host,VDEFAULTBINSERVER.name);
  1284.                        strcpy(mounton,buf1);
  1285.                        }
  1286.                     else
  1287.                        {
  1288.                        sscanf(buf3,"%[^:]",host);
  1289.                        strcpy(mounton,buf1);
  1290.                        }
  1291.  
  1292.                     break;
  1293.       case aix:
  1294.                    /* skip header */
  1295.  
  1296.                     if (buf1[0] == '/')
  1297.                        {
  1298.                        strcpy(host,VDEFAULTBINSERVER.name);
  1299.                        strcpy(mounton,buf2);
  1300.                        }
  1301.                     else
  1302.                        {
  1303.                        strcpy(host,buf1);
  1304.                        strcpy(mounton,buf3);
  1305.                        }
  1306.                     break;
  1307.  
  1308.       case cfnt:    strcpy(mounton,buf2);
  1309.                 strcpy(host,buf1);
  1310.                     break;
  1311.       case unused1:
  1312.       case unused2:
  1313.       case unused3:
  1314.                     break;
  1315.  
  1316.       case cfsco: CfLog(cferror,"Don't understand SCO mount format, no data","");
  1317.  
  1318.       default:
  1319.                     printf("cfengine software error: case %d = %s\n",VSYSTEMHARDCLASS,CLASSTEXT[VSYSTEMHARDCLASS]);
  1320.                     FatalError("System error in GetMountInfo - no such class!");
  1321.       }
  1322.  
  1323.    InstallMountedItem(host,mounton);
  1324.    }
  1325.  
  1326. while (!feof(pp));
  1327.  
  1328. alarm(0);
  1329. signal(SIGALRM,SIG_DFL);
  1330. ReleaseCurrentLock();
  1331. pclose(pp);
  1332. }
  1333.  
  1334. /*******************************************************************/
  1335.  
  1336. MakePaths()
  1337.  
  1338. { struct File *ptr;
  1339.   struct Item *ip1,*ip2;
  1340.   int DirectoriesWrapper();
  1341.   char pathbuff[bufsize],basename[bufsize];
  1342.   
  1343. Banner("Checking directories:");
  1344.  
  1345. for (ptr = VMAKEPATH; ptr != NULL; ptr=ptr->next)
  1346.    {
  1347.    if (IsExcluded(ptr->classes))
  1348.       {
  1349.       continue;
  1350.       }
  1351.  
  1352.    ResetOutputRoute(ptr->log,ptr->inform);
  1353.       
  1354.    if (strncmp(ptr->path,"home/",5) == 0) /* home/subdir */
  1355.       {
  1356.       if (*(ptr->path+4) != '/')
  1357.      {
  1358.      sprintf(OUTPUT,"Illegal use of home in directories: %s\n",ptr->path);
  1359.      CfLog(cferror,OUTPUT,"");
  1360.      continue;
  1361.      }
  1362.       
  1363.       for (ip1 = VHOMEPATLIST; ip1 != NULL; ip1=ip1->next)
  1364.      {
  1365.      for (ip2 = VMOUNTLIST; ip2 != NULL; ip2=ip2->next)
  1366.         {
  1367.         if (IsExcluded(ip2->classes))
  1368.            {
  1369.            continue;
  1370.            }
  1371.         
  1372.         pathbuff[0]='\0';
  1373.         basename[0]='\0';        
  1374.         
  1375.         strcpy(pathbuff,ip2->name);
  1376.         AddSlash(pathbuff);
  1377.         strcat(pathbuff,ip1->name);
  1378.         AddSlash(pathbuff);
  1379.         strcat(pathbuff,"*/");   
  1380.         strcat(pathbuff,ptr->path+5);
  1381.         
  1382.         ExpandWildCardsAndDo(pathbuff,basename,DirectoriesWrapper,ptr);     
  1383.         }
  1384.      }
  1385.       }
  1386.    else
  1387.       {
  1388.       Verbose("MakePath(%s)\n",ptr->path);
  1389.       pathbuff[0]='\0';
  1390.       basename[0]='\0';            
  1391.  
  1392.       ExpandWildCardsAndDo(ptr->path,basename,DirectoriesWrapper,ptr);
  1393.       }
  1394.    ResetOutputRoute('d','d');
  1395.    }
  1396. }
  1397.  
  1398. /*******************************************************************/
  1399.  
  1400. MakeChildLinks()     /* <binserver> should expand to a best fit filesys */
  1401.  
  1402. { struct Link *lp;
  1403.   char *sp, *bp;
  1404.   struct Item *ip;
  1405.   int matched,varstring;
  1406.   struct stat statbuf;
  1407.   short saveenforce;
  1408.   short savesilent;
  1409.  
  1410. if (NOLINKS)
  1411.    {
  1412.    return;
  1413.    }
  1414.  
  1415. Banner("Checking multiple childlinks:");
  1416.  
  1417. for (lp = VCHLINK; lp != NULL; lp = lp->next)
  1418.    {
  1419.    if (IsExcluded(lp->classes))
  1420.       {
  1421.       continue;
  1422.       }
  1423.  
  1424.    saveenforce = ENFORCELINKS;
  1425.    ENFORCELINKS = ENFORCELINKS || lp->force;
  1426.  
  1427.    savesilent = SILENT;
  1428.    SILENT = SILENT || lp->silent;
  1429.  
  1430.    ResetOutputRoute(lp->log,lp->inform);
  1431.    
  1432.    matched = varstring = false;
  1433.  
  1434.    for(ip = VBINSERVERS; ip != NULL && (!matched); ip = ip->next)
  1435.       {
  1436.       CURRENTPATH[0] = CURRENTITEM[0] = '\0';
  1437.  
  1438.       if (strcmp(lp->to,"linkchildren") == 0)           /* linkchildren */
  1439.          {
  1440.          if (stat(lp->from,&statbuf) == -1)
  1441.             {
  1442.             sprintf(OUTPUT,"Makechildlinks() can't stat %s\n",lp->from);
  1443.         CfLog(cferror,OUTPUT,"stat");
  1444.         ResetOutputRoute('d','d');
  1445.             continue;
  1446.             }
  1447.          LinkChildren(lp->from,lp->type,&statbuf,NULL,NULL,NULL,lp);
  1448.          break;
  1449.          }
  1450.  
  1451.       varstring = ExpandVarbinserv(lp->to,CURRENTPATH,ip->name);
  1452.  
  1453.       if (lp->recurse != 0)
  1454.      {
  1455.      matched = RecursiveLink(lp,lp->from,CURRENTPATH,lp->recurse);
  1456.          }
  1457.       else if (LinkChildFiles(lp->from,CURRENTPATH,lp->type,lp->inclusions,lp->exclusions,lp->copy,lp->nofile,lp))
  1458.          {
  1459.          matched = true;
  1460.          }
  1461.       else if (! varstring)
  1462.          {
  1463.          sprintf(OUTPUT,"Error while trying to childlink %s -> %s\n",lp->from,CURRENTPATH);
  1464.      CfLog(cferror,OUTPUT,"");
  1465.          sprintf(OUTPUT,"The directory %s does not exist. Can't link.\n",CURRENTPATH);
  1466.      CfLog(cferror,OUTPUT,"");     
  1467.          }
  1468.  
  1469.       if (! varstring)                       /* don't iterate over binservers if not var */
  1470.          {
  1471.          break;
  1472.          }
  1473.       }
  1474.  
  1475.    ENFORCELINKS = saveenforce;
  1476.    SILENT = savesilent;
  1477.    ResetOutputRoute('d','d');
  1478.  
  1479.    if (matched == false && ip == NULL)
  1480.       {
  1481.       sprintf(OUTPUT,"ChildLink didn't find any server to match %s -> %s\n",lp->from,lp->to);
  1482.       CfLog(cferror,OUTPUT,"");
  1483.       }
  1484.    }
  1485. }
  1486.  
  1487. /*******************************************************************/
  1488.  
  1489. MakeLinks()     /* <binserver> should expand to a best fit filesys */
  1490.  
  1491. { struct Link *lp;
  1492.   char *sp, *bp;
  1493.   struct Item *ip;
  1494.   int matched,varstring;
  1495.   struct stat statbuf;
  1496.   short saveenforce;
  1497.   short savesilent;
  1498.   int LinkFiles(), HardLinkFiles(), AbsoluteLink(), RelativeLink();
  1499.   int (*linkfiles)();
  1500.  
  1501. if (NOLINKS)
  1502.    {
  1503.    return;
  1504.    }
  1505.  
  1506. Banner("Checking links:");
  1507.  
  1508. for (lp = VLINK; lp != NULL; lp = lp->next)
  1509.    {
  1510.    if (IsExcluded(lp->classes))
  1511.       {
  1512.       continue;
  1513.       }
  1514.  
  1515.    ResetOutputRoute(lp->log,lp->inform);
  1516.    
  1517.    switch (lp->type)
  1518.       {
  1519.       case 's':
  1520.                 linkfiles = LinkFiles;
  1521.                 break;
  1522.       case 'r':
  1523.             linkfiles = RelativeLink;
  1524.         break;
  1525.       case 'a':
  1526.             linkfiles = AbsoluteLink;
  1527.                 break;
  1528.       case 'h':
  1529.                 linkfiles = HardLinkFiles;
  1530.                 break;
  1531.       default:
  1532.                 printf("%s: internal error, link type was [%c]\n",VPREFIX,lp->type);
  1533.                 continue;
  1534.       }
  1535.  
  1536.    saveenforce = ENFORCELINKS;
  1537.    ENFORCELINKS = ENFORCELINKS || lp->force;
  1538.  
  1539.    savesilent = SILENT;
  1540.    SILENT = SILENT || lp->silent;
  1541.  
  1542.    matched = varstring = false;
  1543.  
  1544.    for( ip = VBINSERVERS; ip != NULL && (!matched); ip = ip->next)
  1545.       {
  1546.       CURRENTPATH[0] = CURRENTITEM[0] = '\0';
  1547.  
  1548.       varstring = ExpandVarbinserv(lp->to,CURRENTPATH,ip->name);
  1549.  
  1550.       if ((*linkfiles)(lp->from,CURRENTPATH,lp->inclusions,lp->exclusions,lp->copy,lp->nofile,lp))
  1551.          {
  1552.          matched = true;
  1553.          }
  1554.       else if (! varstring)
  1555.          {
  1556.          sprintf(OUTPUT,"Error while trying to link %s -> %s\n",lp->from,CURRENTPATH);
  1557.      CfLog(cferror,OUTPUT,"");
  1558.          }
  1559.  
  1560.       if (! varstring)                       /* don't iterate over binservers if not var */
  1561.          {
  1562.          break;
  1563.          }
  1564.       }
  1565.  
  1566.    ENFORCELINKS = saveenforce;
  1567.    SILENT = savesilent;
  1568.  
  1569.    ResetOutputRoute('d','d');
  1570.    
  1571.    if (matched == false && ip == NULL)
  1572.       {
  1573.       sprintf(OUTPUT,"Links didn't find any file to match %s -> %s\n",lp->from,lp->to);
  1574.       CfLog(cferror,OUTPUT,"");
  1575.       }
  1576.    }
  1577. }
  1578.  
  1579. /*******************************************************************/
  1580.  
  1581. MailCheck()
  1582.  
  1583. { char mailserver[bufsize];
  1584.   char mailhost[maxvarsize];
  1585.   char rmailpath[maxvarsize];
  1586.   char lmailpath[maxvarsize];
  1587.  
  1588.  
  1589. if (VMAILSERVER[0] == '\0')
  1590.    {
  1591.    FatalError("Program does not define a mailserver for this host");
  1592.    }
  1593.  
  1594. Banner("Checking mail spool directory");
  1595.  
  1596. if (getuid() != 0)                            
  1597.    {
  1598.    printf("%s: Only root can alter the mail configuration.\n",VPREFIX);
  1599.    return;
  1600.    }
  1601.  
  1602. sscanf (VMAILSERVER,"%[^:]:%s",mailhost,rmailpath);
  1603.  
  1604. if (VMAILSERVER[0] == '\0')
  1605.    {
  1606.    CfLog(cferror,"\n%s: Host has no defined mailserver!\n","");
  1607.    return;
  1608.    }
  1609.  
  1610. if (strcmp(VDEFAULTBINSERVER.name,mailhost) == 0) /* Is this the mailserver ?*/
  1611.    {
  1612.    MailCheckMore(rmailpath);
  1613.    return;
  1614.    }
  1615.  
  1616. sprintf(lmailpath,"%s:%s",mailhost,VMAILDIR[VSYSTEMHARDCLASS]);
  1617.  
  1618.  
  1619. if (IsItemIn(VMOUNTED,lmailpath))                             /* Remote file system mounted on */
  1620.    {                                                          /* local mail dir - correct      */
  1621.    Verbose("%s: Mail spool area looks ok\n",VPREFIX);
  1622.    return;
  1623.    }
  1624.  
  1625. strcpy(mailserver,VMAILDIR[VSYSTEMHARDCLASS]);
  1626. AddSlash(mailserver);
  1627. strcat(mailserver,".");
  1628.  
  1629. MakeDirectoriesFor(mailserver);                                  /* Check directory is in place */
  1630.  
  1631. if (IsItemIn(VMOUNTED,VMAILSERVER))
  1632.    {
  1633.    if (!SILENT)
  1634.       {
  1635.       Verbose("%s: Warning - the mail directory seems to be mounted as on\n",VPREFIX);
  1636.       Verbose("%s: the remote mailserver and not on the correct local directory\n",VPREFIX);
  1637.       Verbose("%s: Should strictly mount on %s\n",VPREFIX,VMAILDIR[VSYSTEMHARDCLASS]);
  1638.       }
  1639.    return;
  1640.    }
  1641.  
  1642. if (MatchStringInFstab("mail"))
  1643.    {
  1644.    if (!SILENT)
  1645.       {
  1646.       Verbose("%s: Warning - the mail directory seems to be mounted\n",VPREFIX);
  1647.       Verbose("%s: in a funny way. I can find the string <mail> in %s\n",VPREFIX,VFSTAB[VSYSTEMHARDCLASS]);
  1648.       Verbose("%s: but nothing is mounted on %s\n\n",VPREFIX,VMAILDIR[VSYSTEMHARDCLASS]);
  1649.       }
  1650.    return;
  1651.    }
  1652.  
  1653. printf("\n%s: Trying to mount %s\n",VPREFIX,VMAILSERVER);
  1654.  
  1655. if (! DONTDO)
  1656.    {
  1657.    AddToFstab(mailhost,rmailpath,VMAILDIR[VSYSTEMHARDCLASS],"rw",false);
  1658.    }
  1659. else
  1660.    {
  1661.    printf("%s: Need to mount %s:%s on %s\n",VPREFIX,mailhost,rmailpath,mailserver);
  1662.    }
  1663. }
  1664.  
  1665.  
  1666. /*******************************************************************/
  1667.  
  1668.  
  1669. MailCheckMore(rmailpath)
  1670.  
  1671. char *rmailpath;
  1672.  
  1673. { struct stat statbuf;
  1674.  
  1675. Verbose("%s: Maildir is %s on %s\n",VPREFIX,rmailpath,VMAILSERVER); 
  1676.  
  1677. if (strncmp(VMAILSERVER,VFQNAME,strlen(VMAILSERVER)) != 0)
  1678.    { DIR *dirh;
  1679.      struct dirent *dirp;
  1680.      struct stat statbuf;
  1681.  
  1682.    Verbose("%s: Looking closely at the mail directory...\n",VPREFIX);
  1683.  
  1684.    if ((dirh = opendir(rmailpath)) == NULL)
  1685.       {
  1686.       sprintf(OUTPUT,"Can't open directory %s which checking mail directory",rmailpath);
  1687.       CfLog(cferror,OUTPUT,"opendir");
  1688.       return false;
  1689.       }
  1690.  
  1691.    for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
  1692.       {
  1693.       if (!SensibleFile(dirp->d_name,rmailpath,NULL))
  1694.          {
  1695.          continue;
  1696.          }
  1697.  
  1698.       strcpy(VBUFF,rmailpath);
  1699.       AddSlash(VBUFF);
  1700.       strcat(VBUFF,dirp->d_name);
  1701.  
  1702.       if (stat(VBUFF,&statbuf) != -1)
  1703.      {
  1704.      if (getpwuid(statbuf.st_uid) == NULL)
  1705.         {
  1706.         if (TrueVar("WarnNonOwnerMail"))
  1707.            {
  1708.            sprintf(OUTPUT,"File %s in mail dir %s is not owned by any user",dirp->d_name,rmailpath);
  1709.            CfLog(cferror,OUTPUT,"");
  1710.            }
  1711.         
  1712.         if (TrueVar("DeleteNonOwnerMail"))
  1713.            {
  1714.            if (DONTDO)
  1715.           {
  1716.           printf("%s: Delete file %s\n",VPREFIX,VBUFF);
  1717.           }
  1718.            else
  1719.           {
  1720.           sprintf(OUTPUT,"Deleting file %s in mail dir %s not owned by any user",dirp->d_name,rmailpath);
  1721.           CfLog(cferror,OUTPUT,"");
  1722.  
  1723.           if (unlink(VBUFF) == -1)
  1724.              {
  1725.              CfLog(cferror,"","unlink");
  1726.              }
  1727.           }
  1728.            }
  1729.         }
  1730.      }
  1731.  
  1732.       if (strstr(dirp->d_name,"lock") || strstr(dirp->d_name,".tmp"))
  1733.      {
  1734.      Verbose("Ignoring non mailbox file %s\n",dirp->d_name);
  1735.      continue;
  1736.      }
  1737.  
  1738.       if (getpwnam(dirp->d_name) == NULL)
  1739.      {
  1740.      if (TrueVar("WarnNonUserMail"))
  1741.         {
  1742.         sprintf(OUTPUT,"File %s in mail dir %s is not the name of a user",dirp->d_name,rmailpath);
  1743.         CfLog(cferror,OUTPUT,"");
  1744.         }
  1745.      
  1746.      if (TrueVar("DeleteNonUserMail"))
  1747.         {
  1748.         if (DONTDO)
  1749.            {
  1750.            printf("%s: Delete file %s\n",VPREFIX,VBUFF);
  1751.            }
  1752.         else
  1753.            {
  1754.            sprintf(OUTPUT,"Deleting file %s in mail dir %s (not a username)",dirp->d_name,rmailpath);
  1755.            CfLog(cferror,OUTPUT,"");
  1756.            
  1757.            if (unlink(VBUFF) == -1)
  1758.           {
  1759.           CfLog(cferror,"","unlink");
  1760.           }           
  1761.            }
  1762.         }    
  1763.      }
  1764.       }
  1765.    closedir(dirh);
  1766.    Verbose("%s: Done with mail directory\n",VPREFIX);
  1767.    } 
  1768. }
  1769.  
  1770. /*******************************************************************/
  1771.  
  1772. MountFileSystems()
  1773.  
  1774. { FILE *pp;
  1775.   int fd,TimeOut();
  1776.   struct stat statbuf;
  1777.  
  1778. if (! GOTMOUNTINFO || DONTDO)
  1779.    {
  1780.    return;
  1781.    }
  1782.  
  1783. if (getuid() != 0)                            
  1784.    {
  1785.    printf("%s: Only root can mount filesystems.\n",VPREFIX);
  1786.    return;
  1787.    }
  1788.  
  1789. Banner("Mounting filesystems");
  1790.  
  1791. signal(SIGALRM,(void *)TimeOut);
  1792. alarm(RPCTIMEOUT);
  1793.  
  1794. if (VSYSTEMHARDCLASS == cfnt)
  1795.    {
  1796.    /* This is a shell script. Make sure it hasn't been compromised. */
  1797.    if (stat("/etc/fstab",&statbuf) == -1)
  1798.       {
  1799.       if ((fd = creat("/etc/fstab",0755)) > 0)
  1800.      {
  1801.      write(fd,"#!/bin/sh\n\n",10);
  1802.      close(fd);
  1803.      }
  1804.       else
  1805.      {
  1806.      if (statbuf.st_mode & (S_IWOTH | S_IWGRP))
  1807.         {
  1808.         CfLog(cferror,"File /etc/fstab was insecure. Cannot mount filesystems.\n");
  1809.         GOTMOUNTINFO = false;
  1810.         return;
  1811.         }
  1812.      }
  1813.       }
  1814.    }
  1815.  
  1816. if ((pp = cfpopen(VMOUNTCOMM[VSYSTEMHARDCLASS],"r")) == NULL)
  1817.    {
  1818.    sprintf(OUTPUT,"Failed to open pipe from %s\n",VMOUNTCOMM[VSYSTEMHARDCLASS]);
  1819.    CfLog(cferror,OUTPUT,"popen");
  1820.    return;
  1821.    }
  1822.  
  1823. while (!feof(pp))
  1824.    {
  1825.    if (ferror(pp))  /* abortable */
  1826.       {
  1827.       CfLog(cferror,"Error mounting filesystems\n","ferror");
  1828.       break;
  1829.       }
  1830.    
  1831.    ReadLine(VBUFF,bufsize,pp);
  1832.  
  1833.    if (ferror(pp))  /* abortable */
  1834.       {
  1835.       CfLog(cferror,"Error mounting filesystems\n","ferror");
  1836.       break;
  1837.       }
  1838.  
  1839.    if (strstr(VBUFF,"already mounted") || strstr(VBUFF,"exceeded") || strstr(VBUFF,"determined"))
  1840.       {
  1841.       continue;
  1842.       }
  1843.  
  1844.    if (strstr(VBUFF,"not supported"))
  1845.       {
  1846.       continue;
  1847.       }
  1848.  
  1849.    if (strstr(VBUFF,"denied") || strstr(VBUFF,"RPC") || strstr(VBUFF,"root"))
  1850.       {
  1851.       CfLog(cferror,"There was a mount error, trying to mount one of the filesystems on this host.\n","");
  1852.       sprintf(OUTPUT,"%s\n",VBUFF);
  1853.       CfLog(cferror,OUTPUT,"");
  1854.       GOTMOUNTINFO = false;
  1855.       break;
  1856.       }
  1857.  
  1858.    if (strstr(VBUFF,"trying") && !strstr(VBUFF,"NFS version 2"))
  1859.       {
  1860.       CfLog(cferror,"Aborted because MountFileSystems() went into a retry loop.\n","");
  1861.       GOTMOUNTINFO = false;
  1862.       break;
  1863.       }
  1864.    }
  1865.  
  1866. alarm(0);
  1867. signal(SIGALRM,SIG_DFL);
  1868. cfpclose(pp);
  1869. }
  1870.  
  1871. /*******************************************************************/
  1872.  
  1873. CheckRequired()
  1874.  
  1875. { struct Disk *rp;
  1876.   struct Item *ip;
  1877.   int matched,varstring,missing = 0;
  1878.  
  1879. Banner("Checking required filesystems");
  1880.  
  1881. for (rp = VREQUIRED; rp != NULL; rp = rp->next)
  1882.    {
  1883.    if (IsExcluded(rp->classes))
  1884.       {
  1885.       continue;
  1886.       }
  1887.  
  1888.    ResetOutputRoute(rp->log,rp->inform);
  1889.    matched = varstring = false;
  1890.  
  1891.    for(ip = VBINSERVERS; ip != NULL && (!matched); ip = ip->next)
  1892.       {
  1893.       CURRENTPATH[0] = CURRENTITEM[0] = '\0';
  1894.  
  1895.       varstring = ExpandVarbinserv(rp->name,CURRENTPATH,ip->name);
  1896.  
  1897.       if (RequiredFileSystemOkay(CURRENTPATH))  /* simple or reduced item */
  1898.          {
  1899.          Verbose("Filesystem %s looks sensible\n",CURRENTPATH);
  1900.          matched = true;
  1901.          }
  1902.       else if (! varstring)
  1903.          {
  1904.          sprintf(OUTPUT,"The file %s does not exist.\n\n",CURRENTPATH);
  1905.      CfLog(cferror,OUTPUT,"");
  1906.      
  1907.          /* Define the class if there was no freespace option. */
  1908.          if (rp->freespace == -1)
  1909.         {
  1910.         AddRequiredClasses(rp->define);
  1911.         }
  1912.          }
  1913.  
  1914.       if (! varstring)                       /* don't iterate over binservers if not var */
  1915.          {
  1916.          break;
  1917.          }
  1918.  
  1919.       }
  1920.  
  1921.    if ((rp->freespace != -1) && !CheckFreeSpace(CURRENTPATH,rp->freespace))
  1922.      {
  1923.      Verbose("Free space below %d, defining %s\n",rp->freespace, rp->define);
  1924.      AddRequiredClasses(rp->define);
  1925.      }
  1926.  
  1927.    if (matched == false && ip == NULL)
  1928.       {
  1929.       printf(" didn't find any file to match the required filesystem %s\n",rp->name);
  1930.       missing++;
  1931.       }
  1932.    }
  1933.  
  1934. if (missing)
  1935.  
  1936.    { time_t tloc;;
  1937.  
  1938.    if ((tloc = time((time_t *)NULL)) == -1)
  1939.       {
  1940.       printf("Couldn't read system clock\n");
  1941.       }
  1942.    sprintf(OUTPUT,"\n%s: MESSAGE at %s\n\n",ctime(&tloc));
  1943.    CfLog(cferror,OUTPUT,"");
  1944.    sprintf(OUTPUT,"There are %d required file(system)s missing on host <%s>\n",missing,VDEFAULTBINSERVER.name);
  1945.    CfLog(cferror,OUTPUT,"");   
  1946.    CfLog(cferror,"even after all mounts have been attempted.\n","");
  1947.    CfLog(cferror,"This may be caused by a failure to mount a network filesystem (check exports)\n","");
  1948.    sprintf(OUTPUT,"or because no valid server was specified in the program %s\n\n",VINPUTFILE);
  1949.    CfLog(cferror,OUTPUT,"");
  1950.  
  1951.    ResetOutputRoute('d','d');
  1952.    }
  1953. }
  1954.  
  1955. /*******************************************************************/
  1956.  
  1957. TidyFiles()
  1958.  
  1959.    /* Here we start by scanning for any absolute path wildcards */
  1960.    /* After that's finished, we go snooping around the homedirs */
  1961.  
  1962. { char basename[bufsize],pathbuff[bufsize];
  1963.   struct TidyPattern *tlp;
  1964.   struct Tidy *tp;
  1965.   struct Item *ip1,*ip2;
  1966.   struct stat statbuf;
  1967.   int homesearch = 0;
  1968.   int TidyWrapper();
  1969.   int RecHomeTidyWrapper();
  1970.  
  1971. Banner("Tidying by directory");
  1972.  
  1973. for (tp = VTIDY; tp != NULL; tp=tp->next)
  1974.    {
  1975.    if (strncmp(tp->path,"home",4)==0)
  1976.       {
  1977.       for (tlp = tp->tidylist; tlp != NULL; tlp=tlp->next)
  1978.      {
  1979.      if (!IsExcluded(tlp->classes))
  1980.         {
  1981.         homesearch = 1;
  1982.         break;
  1983.         }
  1984.      }
  1985.       continue;
  1986.       }
  1987.  
  1988.    for (tlp = tp->tidylist; tlp != NULL; tlp=tlp->next)
  1989.       {
  1990.       Verbose("Directory %s\n",tp->path);
  1991.       strcpy(VBUFF,tp->path);
  1992.       AddSlash(VBUFF);
  1993.       strcat(VBUFF,tlp->pattern);
  1994.  
  1995.       if (stat(VBUFF,&statbuf) != -1)   /* not lstat - could confuse user */
  1996.          {
  1997.          if (S_ISDIR(statbuf.st_mode))
  1998.             {
  1999.         if (! tlp->rmdirs)          /* Are we allowed to rm empty dirs? */
  2000.            {
  2001.                Verbose("%s: will not delete directories (matching %s)!\n",VPREFIX,tlp->pattern);
  2002.            Verbose("%s: Applies to %s\n",VPREFIX,VBUFF);
  2003.                DeleteTidyList(tp->tidylist);
  2004.            tp->tidylist = NULL;
  2005.                continue;
  2006.            }
  2007.             }
  2008.          }
  2009.       }
  2010.  
  2011.    basename[0] = '\0';
  2012.  
  2013.    ExpandWildCardsAndDo(tp->path,basename,TidyWrapper,tp);
  2014.    
  2015.    DeleteTidyList(tp->tidylist);
  2016.    tp->tidylist = NULL;
  2017.    }
  2018.  
  2019.  
  2020. Debug2("End PATHTIDY:\n");
  2021.  
  2022. if (!homesearch)                           /* If there are "home" wildcards */
  2023.    {                                 /* Don't go rummaging around the disks */
  2024.    Verbose("No home patterns to search\n");
  2025.    return;
  2026.    }
  2027.  
  2028. if (getuid() != 0)                            
  2029.    {
  2030.    printf("%s: Only root can delete others' files.\n",VPREFIX);
  2031.    return;
  2032.    }
  2033.  
  2034.  
  2035. CfLog(cfinform,"Tidying home directories","");
  2036.  
  2037. if (!MountPathDefined())
  2038.    {
  2039.    return;
  2040.    }
  2041.  
  2042. for (ip1 = VHOMEPATLIST; ip1 != NULL; ip1=ip1->next)
  2043.    {
  2044.    for (ip2 = VMOUNTLIST; ip2 != NULL; ip2=ip2->next)
  2045.       {
  2046.       if (IsExcluded(ip2->classes))
  2047.      {
  2048.      continue;
  2049.      }
  2050.       pathbuff[0]='\0';
  2051.       basename[0]='\0';
  2052.       strcpy(pathbuff,ip2->name);
  2053.       AddSlash(pathbuff);
  2054.       strcat(pathbuff,ip1->name);
  2055.  
  2056.       ExpandWildCardsAndDo(pathbuff,basename,RecHomeTidyWrapper,NULL);
  2057.       }
  2058.    }
  2059.  
  2060. CfLog(cfinform,"Done with home directories","");
  2061. }
  2062.  
  2063. /*******************************************************************/
  2064.  
  2065. Scripts()
  2066.  
  2067. { struct ShellComm *ptr;
  2068.   char line[bufsize];
  2069.   char comm[20], *sp;
  2070.   char execstr[bufsize];
  2071.   int print,TimeOut();
  2072.   uid_t myuid;
  2073.   gid_t mygid;
  2074.   FILE *pp;
  2075.  
  2076. Banner("Running shell commands");
  2077.  
  2078. for (ptr = VSCRIPT; ptr != NULL; ptr=ptr->next)
  2079.    {
  2080.    if (IsExcluded(ptr->classes))
  2081.       {
  2082.       continue;
  2083.       }
  2084.  
  2085.    ResetOutputRoute(ptr->log,ptr->inform);
  2086.    myuid = -1;
  2087.    mygid = -1;
  2088.    
  2089.    if (!GetLock(ASUniqueName("shellcommand"),CanonifyName(ptr->name),VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  2090.       {
  2091.       continue;
  2092.       }
  2093.    
  2094.    sprintf(OUTPUT,"Executing script %s...(timeout=%d,uid=%d,gid=%d)\n",ptr->name,ptr->timeout,ptr->uid,ptr->gid);
  2095.    CfLog(cfinform,OUTPUT,"");
  2096.  
  2097.    if (ptr->uid != (uid_t) -1)
  2098.       {
  2099.       myuid = getuid();
  2100.       Verbose("Changing effective uid to %d\n",ptr->uid);
  2101.       
  2102.       if (seteuid(ptr->uid) == -1)
  2103.      {
  2104.      sprintf(OUTPUT,"Couldn't set effective uid to %d\n",ptr->uid);
  2105.      CfLog(cferror,OUTPUT,"seteuid");
  2106.      ReleaseCurrentLock();
  2107.      continue;
  2108.      }
  2109.       }
  2110.  
  2111.    if (ptr->gid != (gid_t) -1)
  2112.       {
  2113.       mygid = getgid();
  2114.       Verbose("Changing effective gid to %d\n",ptr->gid);      
  2115.  
  2116.       if (setegid(ptr->gid) == -1)
  2117.      {
  2118.      sprintf(OUTPUT,"Couldn't set effective gid to %d\n",ptr->uid);
  2119.      CfLog(cferror,OUTPUT,"seteuid");
  2120.      ReleaseCurrentLock();
  2121.      continue;
  2122.      }
  2123.       }
  2124.    
  2125.    if (DONTDO)
  2126.       {
  2127.       printf("%s: execute script %s\n",VPREFIX,ptr->name);
  2128.       }
  2129.    else
  2130.       {
  2131.       for (sp = ptr->name; *sp != ' ' && *sp != '\0'; sp++)
  2132.      {
  2133.      }
  2134.  
  2135.       if (sp - 10 >= ptr->name)
  2136.      {
  2137.      sp -= 10;   /* copy 15 most relevant characters of command */
  2138.      }
  2139.       else
  2140.      {
  2141.      sp = ptr->name;
  2142.      }
  2143.  
  2144.       bzero(comm,20);
  2145.       bzero(execstr,bufsize);
  2146.  
  2147.       strncpy(comm,sp,15);
  2148.  
  2149.       if (ptr->timeout != 0)
  2150.      {
  2151.          signal(SIGALRM,(void *)TimeOut);
  2152.          alarm(ptr->timeout);
  2153.          }
  2154.  
  2155.       switch (ptr->useshell)
  2156.      {
  2157.      case 'y':  pp = cfpopen_sh(ptr->name,"r");
  2158.                 break;
  2159.      default:   pp = cfpopen(ptr->name,"r");
  2160.                 break;         
  2161.      }
  2162.  
  2163.       if (pp == NULL)
  2164.      {
  2165.      sprintf(OUTPUT,"Couldn't open pipe to command %s\n",ptr->name);
  2166.      CfLog(cferror,OUTPUT,"popen");
  2167.      ResetOutputRoute('d','d');
  2168.      RevertId(myuid,mygid);
  2169.      ReleaseCurrentLock();
  2170.      continue;
  2171.      } 
  2172.       
  2173.       while (!feof(pp))
  2174.      {
  2175.      if (ferror(pp))  /* abortable */
  2176.         {
  2177.         sprintf(OUTPUT,"Shell command pipe %s\n",ptr->name);
  2178.         CfLog(cferror,OUTPUT,"ferror");
  2179.         break;
  2180.         }
  2181.      
  2182.      ReadLine(line,bufsize,pp);
  2183.  
  2184.      if (ferror(pp))  /* abortable */
  2185.         {
  2186.         sprintf(OUTPUT,"Shell command pipe %s\n",ptr->name);
  2187.         CfLog(cferror,OUTPUT,"ferror");
  2188.         break;
  2189.         }
  2190.  
  2191.      print = false;
  2192.      
  2193.      for (sp = line; *sp != '\0'; sp++)
  2194.         {
  2195.         if (! isspace(*sp))
  2196.            {
  2197.            print = true;
  2198.            break;
  2199.            }
  2200.         }
  2201.      
  2202.      if (print)
  2203.         {
  2204.         printf("%s:%s: %s\n",VPREFIX,comm,line);
  2205.         }
  2206.      }
  2207.       
  2208.       cfpclose_def(pp,ptr->defines);
  2209.       }
  2210.  
  2211.    if (ptr->timeout != 0)
  2212.       {
  2213.       alarm(0);
  2214.       signal(SIGALRM,SIG_DFL);
  2215.       }
  2216.  
  2217.    sprintf(OUTPUT,"Finished script %s\n",ptr->name);
  2218.    CfLog(cfinform,OUTPUT,"");
  2219.  
  2220.    ResetOutputRoute('d','d');
  2221.    RevertId(myuid,mygid);
  2222.    ReleaseCurrentLock();
  2223.    }
  2224. }
  2225.  
  2226. /*******************************************************************/
  2227.  
  2228. GetSetuidLog()
  2229.  
  2230. { struct Item *filetop = NULL;
  2231.   struct Item *ip;
  2232.   FILE *fp;
  2233.   char *sp;
  2234.  
  2235. if (getuid() != 0)                     /* Ignore this if not root */
  2236.    {
  2237.    return;
  2238.    }
  2239.  
  2240. if ((fp = fopen(VSETUIDLOG,"r")) == NULL)
  2241.    {
  2242.    }
  2243. else
  2244.    {
  2245.    while (!feof(fp))
  2246.       {
  2247.       ReadLine(VBUFF,bufsize,fp);
  2248.  
  2249.       if (strlen(VBUFF) == 0)
  2250.          {
  2251.          continue;
  2252.          }
  2253.  
  2254.       if ((ip = (struct Item *)malloc (sizeof(struct Item))) == NULL)
  2255.          {
  2256.          perror("malloc");
  2257.          FatalError("GetSetuidList() couldn't allocate memory #1");
  2258.          }
  2259.  
  2260.       if ((sp = malloc (strlen(VBUFF)+2)) == NULL)
  2261.          {
  2262.          perror("malloc");
  2263.          FatalError("GetSetuidList() couldn't allocate memory #2");
  2264.          }
  2265.  
  2266.       if (filetop == NULL)
  2267.          {
  2268.          VSETUIDLIST = filetop = ip;
  2269.          }
  2270.       else
  2271.          {
  2272.          filetop->next = ip;
  2273.          }
  2274.  
  2275.       Debug2("SETUID-LOG: %s\n",VBUFF);
  2276.  
  2277.       strcpy(sp,VBUFF);
  2278.       ip->name = sp;
  2279.       ip->next = NULL;
  2280.       filetop = ip;
  2281.       }
  2282.  
  2283.    fclose(fp);
  2284.    }
  2285.  
  2286. }
  2287.  
  2288. /*******************************************************************/
  2289.  
  2290. CheckFiles()                         /* Check through file systems */
  2291.  
  2292. { struct File *ptr;
  2293.   int CheckFileWrapper();
  2294.   char buffer[bufsize];
  2295.   short savetravlinks = TRAVLINKS;
  2296.   short savekilloldlinks = KILLOLDLINKS;
  2297.  
  2298. Banner("Checking files");
  2299.  
  2300. if (TRAVLINKS && (VERBOSE || DEBUG || D2))
  2301.    {
  2302.    printf("(Default in switched to purge stale links...)\n");
  2303.    }
  2304.  
  2305. for (ptr = VFILE; ptr != NULL; ptr=ptr->next)
  2306.    {
  2307.    if (IsExcluded(ptr->classes))
  2308.       {
  2309.       continue;
  2310.       }
  2311.  
  2312.    TRAVLINKS = savetravlinks;
  2313.  
  2314.    if (ptr->travlinks == 'T')
  2315.       {
  2316.       TRAVLINKS = true;
  2317.       }
  2318.    else if (ptr->travlinks == 'F')
  2319.       {
  2320.       TRAVLINKS = false;
  2321.       }
  2322.    else if (ptr->travlinks == 'K')
  2323.       {
  2324.       KILLOLDLINKS = true;
  2325.       }
  2326.  
  2327.    ResetOutputRoute(ptr->log,ptr->inform);
  2328.  
  2329.    if (strncmp(ptr->path,"home",4) == 0)
  2330.       {
  2331.       CheckHome(ptr);
  2332.       continue;
  2333.       }
  2334.  
  2335.    Verbose("Checking file(s) in %s\n",ptr->path);
  2336.  
  2337.    buffer[0] = '\0';
  2338.    ExpandWildCardsAndDo(ptr->path,buffer,CheckFileWrapper,ptr);
  2339.  
  2340.    ResetOutputRoute('d','d');
  2341.    TRAVLINKS = savetravlinks;
  2342.    KILLOLDLINKS = savekilloldlinks;
  2343.    }
  2344. }
  2345.  
  2346. /*******************************************************************/
  2347.  
  2348. SaveSetuidLog()
  2349.  
  2350. { FILE *fp;
  2351.   struct Item *ip;
  2352.  
  2353.  
  2354. if (getuid() != 0)                     /* Ignore this if not root */
  2355.    {
  2356.    return;
  2357.    }
  2358.  
  2359. if (! DONTDO)
  2360.    {
  2361.    if ((fp = fopen(VSETUIDLOG,"w")) == NULL)
  2362.       {
  2363.       sprintf(OUTPUT,"Can't open %s for writing\n",VSETUIDLOG);
  2364.       CfLog(cferror,OUTPUT,"fopen");
  2365.       return;
  2366.       }
  2367.  
  2368.    Verbose("Saving the setuid log in %s\n",VSETUIDLOG);
  2369.  
  2370.    for (ip = VSETUIDLIST; ip != NULL; ip=ip->next)
  2371.       {
  2372.       if (!isspace(*(ip->name)) && strlen(ip->name) != 0)
  2373.          {                         
  2374.          fprintf(fp,"%s\n",ip->name);
  2375.          Debug2("SAVE-SETUID-LOG: %s\n",ip->name);
  2376.          }
  2377.       }
  2378.  
  2379.    fclose(fp);
  2380.    chmod(VSETUIDLOG,0600);
  2381.    }
  2382. }
  2383.  
  2384. /*******************************************************************/
  2385.  
  2386. DisableFiles()
  2387.  
  2388. { struct Disable *dp;
  2389.   struct stat statbuf;
  2390.  
  2391. Banner("Disable files");
  2392.  
  2393. for (dp = VDISABLELIST; dp != NULL; dp=dp->next)
  2394.    {
  2395.    if (IsExcluded(dp->classes))
  2396.       {
  2397.       continue;
  2398.       }
  2399.  
  2400.    ResetOutputRoute(dp->log,dp->inform);
  2401.    
  2402.    if (lstat(dp->name,&statbuf) == -1)
  2403.       {
  2404.       Verbose("Filetype %s, %s is not there - ok\n",dp->type,dp->name);
  2405.       continue;
  2406.       }
  2407.  
  2408.    Verbose("Disable checking %s\n",dp->name);
  2409.  
  2410.    if (S_ISDIR(statbuf.st_mode))
  2411.       {
  2412.       sprintf(OUTPUT,"Warning %s is a directory.\n",dp->name);
  2413.       CfLog(cferror,OUTPUT,"");
  2414.       CfLog(cferror,"I refuse to rename/delete a directory!\n\n","");
  2415.       ResetOutputRoute('d','d');
  2416.       continue;
  2417.       }
  2418.  
  2419.    if (S_ISLNK(statbuf.st_mode))
  2420.       {
  2421.       if (strcmp(dp->type,"file") == 0)
  2422.          {
  2423.          Verbose("%s: %s is a link, not disabling\n",VPREFIX,dp->name);
  2424.      ResetOutputRoute('d','d');
  2425.          continue;
  2426.          }
  2427.  
  2428.       if (readlink(dp->name,VBUFF,bufsize) == -1)
  2429.          {
  2430.          sprintf(OUTPUT,"DisableFiles() can't read link %s\n",dp->name);
  2431.      CfLog(cferror,OUTPUT,"readlink");
  2432.      ResetOutputRoute('d','d');
  2433.          continue;
  2434.          }
  2435.  
  2436.       printf("%s: Deleting link %s -> %s\n",VPREFIX,dp->name,VBUFF);
  2437.  
  2438.       if (! DONTDO)
  2439.          {
  2440.          if (unlink(dp->name) == -1)
  2441.             {
  2442.             sprintf(OUTPUT,"Error while unlinking %s\n",dp->name);
  2443.             CfLog(cferror,OUTPUT,"unlink");
  2444.         ResetOutputRoute('d','d');
  2445.             continue;
  2446.             }
  2447.      
  2448.      AddMultipleClasses(dp->defines);
  2449.          }
  2450.       }
  2451.    else
  2452.       {
  2453.       if (! S_ISREG(statbuf.st_mode))
  2454.          {
  2455.          Verbose("%s: %s is not a plain file - won't disable\n",VPREFIX,dp->name);
  2456.      ResetOutputRoute('d','d');
  2457.          continue;
  2458.          }
  2459.  
  2460.       if (strcmp(dp->type,"link") == 0)
  2461.          {
  2462.          Verbose("%s: %s is a file, not disabling\n",VPREFIX,dp->name);
  2463.      ResetOutputRoute('d','d');
  2464.          continue;
  2465.          }
  2466.  
  2467.       if (stat(dp->name,&statbuf) == -1)
  2468.          {
  2469.          CfLog(cferror,"Internal; error in Disable\n","");
  2470.      ResetOutputRoute('d','d');
  2471.      return;
  2472.          }
  2473.  
  2474.       if (dp->size != cfnosize)
  2475.      {
  2476.          switch (dp->comp)
  2477.         {
  2478.             case '<':  if (statbuf.st_size < dp->size)
  2479.                       {
  2480.                   Verbose("cfengine %s is smaller than %d bytes\n",dp->name,dp->size);
  2481.                   break;
  2482.                       }
  2483.                    Verbose("Size is okay\n");
  2484.                ResetOutputRoute('d','d');
  2485.                    continue;
  2486.             
  2487.            case '=':  if (statbuf.st_size == dp->size)
  2488.                       {
  2489.                   Verbose("cfengine %s is equal to %d bytes\n",dp->name,dp->size);
  2490.                   break;
  2491.                       }
  2492.                     Verbose("Size is okay\n");
  2493.             ResetOutputRoute('d','d');
  2494.             continue;
  2495.                
  2496.         default: if (statbuf.st_size > dp->size)
  2497.                       {
  2498.                   Verbose("cfengine %s is larger than %d bytes\n",dp->name,dp->size);
  2499.                   break;
  2500.                       }
  2501.                    Verbose("Size is okay\n");
  2502.                ResetOutputRoute('d','d');
  2503.                    continue;
  2504.         }
  2505.      }
  2506.  
  2507.       if (dp->rotate == 0)
  2508.          {
  2509.          strcpy(CURRENTPATH,dp->name);
  2510.          strcat(CURRENTPATH,".cfdisabled");
  2511.  
  2512.          sprintf(OUTPUT,"Disabling file %s\n",dp->name);
  2513.          CfLog(cfinform,OUTPUT,"");
  2514.      
  2515.          if (! DONTDO)
  2516.             {
  2517.         chmod(dp->name, (mode_t)0400);
  2518.  
  2519.         if (! IsItemIn(VREPOSLIST,CURRENTPATH))
  2520.            {
  2521.                if (rename(dp->name,CURRENTPATH) == -1)
  2522.                   {
  2523.                   sprintf(OUTPUT,"Error occurred while renaming %s\n",dp->name);
  2524.                   CfLog(cferror,OUTPUT,"rename");
  2525.           ResetOutputRoute('d','d');
  2526.                   continue;
  2527.               }
  2528.  
  2529.            if (Repository(CURRENTPATH))
  2530.               {
  2531.               unlink(CURRENTPATH);
  2532.               }
  2533.            
  2534.            AddMultipleClasses(dp->defines);
  2535.            }
  2536.             }
  2537.          }
  2538.       else if (dp->rotate == CF_TRUNCATE)
  2539.      {
  2540.          sprintf(OUTPUT,"Truncating (emptying) %s\n",dp->name);
  2541.      CfLog(cfinform,OUTPUT,"");
  2542.      
  2543.      if (! DONTDO)
  2544.         {
  2545.             TruncateFile(dp->name);
  2546.         AddMultipleClasses(dp->defines);
  2547.         }
  2548.      }
  2549.       else
  2550.      {
  2551.      sprintf(OUTPUT,"Rotating files %s by %d\n",dp->name,dp->rotate);
  2552.      CfLog(cfinform,OUTPUT,"");
  2553.  
  2554.      if (!DONTDO)
  2555.         {
  2556.         RotateFiles(dp->name,dp->rotate);
  2557.         AddMultipleClasses(dp->defines);
  2558.         }
  2559.      }
  2560.       }
  2561.    ResetOutputRoute('d','d');
  2562.    }
  2563. }
  2564.  
  2565. /*******************************************************************/
  2566.  
  2567. MountHomeBinServers()
  2568.  
  2569. { struct Item *mp;
  2570.   char host[maxvarsize];
  2571.   char mountdir[bufsize];
  2572.   char maketo[bufsize];
  2573.  
  2574. if (! GOTMOUNTINFO)
  2575.    {
  2576.    CfLog(cfinform,"Incomplete mount info due to RPC failure.\n","");
  2577.    sprintf(OUTPUT,"%s will not be modified on this pass!\n\n",VPREFIX,VFSTAB[VSYSTEMHARDCLASS]);
  2578.    CfLog(cfinform,OUTPUT,"");
  2579.    return;
  2580.    }
  2581.  
  2582. if (getuid() != 0)                            
  2583.    {
  2584.    printf("%s:Only root can mount filesystems.\n",VPREFIX);
  2585.    return;
  2586.    }
  2587.  
  2588. Banner("Checking home and binservers");
  2589.  
  2590. for (mp = VMOUNTABLES; mp != NULL; mp=mp->next)
  2591.    {
  2592.    sscanf(mp->name,"%[^:]:%s",host,mountdir);
  2593.  
  2594.    Debug("Mount: checking %s\n",mp->name);
  2595.  
  2596.    strcpy(maketo,mountdir);
  2597.  
  2598.    if (maketo[strlen(maketo)-1] == '/')
  2599.       {
  2600.       strcat(maketo,".");
  2601.       }
  2602.    else
  2603.       {
  2604.       strcat(maketo,"/.");
  2605.       }
  2606.  
  2607.    if (strcmp(host,VDEFAULTBINSERVER.name) == 0) /* A host never mounts itself nfs */
  2608.       {
  2609.       Debug("Skipping host %s\n",host);
  2610.       continue;
  2611.       }
  2612.  
  2613.    if (IsHomeDir(mountdir))
  2614.       {
  2615.       if (!IsItemIn(VMOUNTED,mp->name) && IsItemIn(VHOMESERVERS,host))
  2616.          {
  2617.          MakeDirectoriesFor(maketo);
  2618.          AddToFstab(host,mountdir,mountdir,"rw",false);
  2619.          }
  2620.       else if (IsItemIn(VHOMESERVERS,host))
  2621.      {
  2622.      AddToFstab(host,mountdir,mountdir,"rw",true);
  2623.      }
  2624.       }
  2625.    else
  2626.       {
  2627.       if (!IsItemIn(VMOUNTED,mp->name) && IsItemIn(VBINSERVERS,host))
  2628.          {
  2629.          MakeDirectoriesFor(maketo);
  2630.          AddToFstab(host,mountdir,mountdir,"rw",false);
  2631.          }
  2632.       else if (IsItemIn(VBINSERVERS,host))
  2633.          {
  2634.      AddToFstab(host,mountdir,mountdir,"rw",true);
  2635.          }
  2636.       }
  2637.    }
  2638. }
  2639.  
  2640.  
  2641. /*********************************************************************/
  2642.  
  2643. MountMisc()
  2644.  
  2645. { struct MiscMount *mp;
  2646.   char host[maxvarsize];
  2647.   char mountdir[bufsize];
  2648.   char maketo[bufsize];
  2649.   char mtpt[bufsize];
  2650.  
  2651. if (! GOTMOUNTINFO)
  2652.    {
  2653.    CfLog(cfinform,"Incomplete mount info due to RPC failure.\n","");
  2654.    sprintf(OUTPUT,"%s will not be modified on this pass!\n\n",VPREFIX,VFSTAB[VSYSTEMHARDCLASS]);
  2655.    CfLog(cfinform,OUTPUT,"");
  2656.    return;
  2657.    }
  2658.  
  2659. if (getuid() != 0)                            
  2660.    {
  2661.    printf("%s: Only root can mount filesystems.\n",VPREFIX);
  2662.    return;
  2663.    }
  2664.  
  2665. Banner("Checking miscellaneous mountables:");
  2666.  
  2667. for (mp = VMISCMOUNT; mp != NULL; mp=mp->next)
  2668.    {
  2669.    sscanf(mp->from,"%[^:]:%s",host,mountdir);
  2670.  
  2671.    strcpy(maketo,mp->onto);
  2672.  
  2673.    if (maketo[strlen(maketo)-1] == '/')
  2674.       {
  2675.       strcat(maketo,".");
  2676.       }
  2677.    else
  2678.       {
  2679.       strcat(maketo,"/.");
  2680.       }
  2681.  
  2682.    if (strcmp(host,VDEFAULTBINSERVER.name) == 0) /* A host never mounts itself nfs */
  2683.       {
  2684.       continue;
  2685.       }
  2686.  
  2687.    sprintf(mtpt,"%s:%s",host,mp->onto);
  2688.    
  2689.    if (!IsItemIn(VMOUNTED,mtpt))
  2690.       {
  2691.       MakeDirectoriesFor(maketo);
  2692.       AddToFstab(host,mountdir,mp->onto,mp->options,false);
  2693.       }
  2694.    else
  2695.       {
  2696.       AddToFstab(host,mountdir,mp->onto,mp->options,true);
  2697.       }
  2698.    }
  2699. }
  2700.  
  2701. /*********************************************************************/
  2702.  
  2703. Unmount()
  2704.  
  2705. { struct UnMount *ptr;
  2706.   char comm[bufsize];
  2707.   char fs[bufsize];
  2708.   struct Item *filelist, *item, *search;
  2709.   struct stat statbuf;
  2710.   FILE *pp;
  2711.  
  2712. Banner("Checking unmounts\n");
  2713.  
  2714. if (getuid() != 0)                            
  2715.    {
  2716.    printf("%s: Only root can unmount filesystems.\n",VPREFIX);
  2717.    return;
  2718.    }
  2719.  
  2720. filelist = NULL;
  2721.  
  2722. if (! LoadItemList(&filelist,VFSTAB[VSYSTEMHARDCLASS]))
  2723.    {
  2724.    sprintf(OUTPUT,"Couldn't open %s!\n",VFSTAB[VSYSTEMHARDCLASS]);
  2725.    CfLog(cferror,OUTPUT,"");
  2726.    return;
  2727.    }
  2728.  
  2729. NUMBEROFEDITS = 0;
  2730.  
  2731. for (ptr=VUNMOUNT; ptr != NULL; ptr=ptr->next)
  2732.    {
  2733.    if (IsExcluded(ptr->classes))
  2734.       {
  2735.       continue;
  2736.       }
  2737.  
  2738.    fs[0] = '\0';
  2739.  
  2740.    sscanf(ptr->name,"%*[^:]:%s",fs);
  2741.  
  2742.    if (strlen(fs) == 0)
  2743.       {
  2744.       continue;
  2745.       }
  2746.    
  2747.    sprintf(OUTPUT,"Unmount filesystem %s on %s\n",fs,ptr->name);
  2748.    CfLog(cfverbose,OUTPUT,"");
  2749.  
  2750.    if (strcmp(fs,"/") == 0 || strcmp(fs,"/usr") == 0)
  2751.       {
  2752.       CfLog(cfinform,"Request to unmount / or /usr is refused!\n","");
  2753.       continue;
  2754.       }
  2755.  
  2756.    if (IsItemIn(VMOUNTED,ptr->name) && (! DONTDO))
  2757.       {
  2758.       sprintf(comm,"%s %s",VUNMOUNTCOMM[VSYSTEMHARDCLASS],fs);
  2759.  
  2760.       if ((pp = cfpopen(comm,"r")) == NULL)
  2761.          {
  2762.          sprintf(OUTPUT,"Failed to open pipe from %s\n",VUNMOUNTCOMM[VSYSTEMHARDCLASS]);
  2763.      CfLog(cferror,OUTPUT,"");
  2764.          return;
  2765.          }
  2766.  
  2767.       ReadLine(VBUFF,bufsize,pp);
  2768.  
  2769.       if (strstr(VBUFF,"busy") || strstr(VBUFF,"Busy"))
  2770.          {
  2771.          sprintf(OUTPUT,"umount warned that the device under %s\n",ptr->name);
  2772.      CfLog(cfinform,OUTPUT,"");
  2773.          CfLog(cfinform,"was busy. Cannot unmount that device.\n","");
  2774.          }
  2775.  
  2776.       cfpclose(pp);
  2777.       }
  2778.  
  2779.    if (ptr->deletedir == 't')
  2780.       {
  2781.       if (stat(fs,&statbuf) != -1)
  2782.      {
  2783.      if ( ! S_ISDIR(statbuf.st_mode))
  2784.         {
  2785.         sprintf(OUTPUT,"Warning! %s was not a directory.\n",fs);
  2786.         CfLog(cfinform,OUTPUT,"");
  2787.         CfLog(cfinform,"(Unmount) will not delete this!\n","");
  2788.         KillOldLink(fs);
  2789.         }
  2790.      else if (! DONTDO)
  2791.         {
  2792.         if (rmdir(fs) == -1)
  2793.            {
  2794.            sprintf(OUTPUT,"Unable to remove the directory %s\n",fs);
  2795.            CfLog(cferror,OUTPUT,"rmdir");
  2796.            } 
  2797.         else
  2798.            {
  2799.            sprintf(OUTPUT,"Removing directory %s\n",ptr->name);
  2800.            CfLog(cfinform,OUTPUT,"");
  2801.            }
  2802.         }
  2803.      }
  2804.       }
  2805.       
  2806.    if (ptr->deletefstab == 't')
  2807.       {
  2808.       if (VSYSTEMHARDCLASS == aix)
  2809.      {
  2810.      strcpy (VBUFF,fs);
  2811.      strcat (VBUFF,":");
  2812.      
  2813.      item = LocateNextItemContaining(filelist,VBUFF);
  2814.      
  2815.      if (item->next == NULL)
  2816.         {
  2817.         sprintf(OUTPUT,"Bad format in %s\n",VFSTAB[aix]);
  2818.         CfLog(cferror,OUTPUT,"");
  2819.         }
  2820.      
  2821.      DeleteItem(&filelist,item->next);
  2822.      
  2823.      while (strstr(item->next->name,"="))
  2824.         {
  2825.         DeleteItem(&filelist,item->next);    /* DeleteItem(NULL) is harmless */
  2826.         }
  2827.      }
  2828.       else
  2829.      {
  2830.      Debug("Trying to delete filesystem %s from list\n",ptr->name);
  2831.      strcpy (VBUFF,ptr->name);
  2832.      
  2833.      if (VSYSTEMHARDCLASS == ultrx)   /* ensure name is no just a substring */
  2834.         {
  2835.         strcat (VBUFF,":");
  2836.         DeleteItemContaining(&filelist,VBUFF);
  2837.         }
  2838.      else
  2839.         {
  2840.         strcat (VBUFF," ");
  2841.         DeleteItemContaining(&filelist,VBUFF);
  2842.         VBUFF[strlen(VBUFF)-1] = '\t';
  2843.         DeleteItemContaining(&filelist,VBUFF);
  2844.         }
  2845.      }
  2846.       }
  2847.    }
  2848.  
  2849. if ((! DONTDO) && (NUMBEROFEDITS > 0))
  2850.    {
  2851.    SaveItemList(filelist,VFSTAB[VSYSTEMHARDCLASS]);
  2852.    }
  2853.  
  2854. DeleteItemList(filelist);
  2855. }
  2856.  
  2857. /*********************************************************************/
  2858.  
  2859. EditFiles()
  2860.  
  2861. { struct Edit *ptr;
  2862.  
  2863. Banner("Editing files");
  2864.  
  2865. for (ptr=VEDITLIST; ptr!=NULL; ptr=ptr->next)
  2866.    {
  2867.    if (strncmp(ptr->fname,"home",4) == 0)
  2868.       {
  2869.       DoEditHomeFiles(ptr);
  2870.       }
  2871.    else
  2872.       {
  2873.       WrapDoEditFile(ptr);
  2874.       }
  2875.    }
  2876.  
  2877. EDITVERBOSE = false;
  2878. }
  2879.  
  2880. /*******************************************************************/
  2881.  
  2882. CheckResolv()
  2883.  
  2884. { struct Item *filebase = NULL, *referencefile = NULL;
  2885.   struct Item *ip, *ip2;
  2886.   FILE *fp;
  2887.   char ch;
  2888.   int fd, existed = true;
  2889.  
  2890. Verbose("Checking config in %s\n",VRESOLVCONF[VSYSTEMHARDCLASS]);
  2891.   
  2892. if (VDOMAIN == NULL)
  2893.    {
  2894.    CfLog(cferror,"Domain name not specified. Can't configure resolver\n");
  2895.    return;
  2896.    }
  2897.  
  2898. if (getuid() != 0)                            
  2899.    {
  2900.    printf("%s: Only root can configure the resolver.\n",VPREFIX);
  2901.    return;
  2902.    }
  2903.  
  2904. if (! LoadItemList(&referencefile,VRESOLVCONF[VSYSTEMHARDCLASS]))
  2905.    {
  2906.    sprintf(OUTPUT,"Trying to create %s\n",VRESOLVCONF[VSYSTEMHARDCLASS]);
  2907.    CfLog(cfinform,OUTPUT,"");
  2908.    existed = false;
  2909.    
  2910.    if ((fd = creat(VRESOLVCONF[VSYSTEMHARDCLASS],0644)) == -1)
  2911.       {
  2912.       sprintf(OUTPUT,"Unable to create file %s\n",VRESOLVCONF[VSYSTEMHARDCLASS]);
  2913.       CfLog(cferror,OUTPUT,"creat");
  2914.       return;
  2915.       }
  2916.    else
  2917.       {
  2918.       close(fd);
  2919.       }
  2920.    }
  2921.  
  2922. if (existed)
  2923.    {
  2924.    LoadItemList(&filebase,VRESOLVCONF[VSYSTEMHARDCLASS]);
  2925.    }
  2926.  
  2927. for (ip = filebase; ip != NULL; ip=ip->next)
  2928.    {
  2929.    if (strlen(ip->name) == 0)
  2930.       {
  2931.       continue;
  2932.       }
  2933.  
  2934.    ch = *(ip->name+strlen(ip->name)-2);
  2935.  
  2936.    if (isspace(ch))
  2937.       {
  2938.       sprintf(OUTPUT,"Deleted line %s ended with a space in %s.\n",ip->name,VRESOLVCONF[VSYSTEMHARDCLASS]);
  2939.       CfLog(cfinform,OUTPUT,"");
  2940.       CfLog(cfinform,"The resolver doesn't understand this.\n","");
  2941.       DeleteItem(&filebase,ip);
  2942.       }
  2943.    else if (isspace(*(ip->name)))
  2944.       {
  2945.       sprintf(OUTPUT,"Deleted line %s started with a space in %s.\n",ip->name,VRESOLVCONF[VSYSTEMHARDCLASS]);
  2946.       CfLog(cfinform,OUTPUT,"");
  2947.       CfLog(cfinform,"The resolver doesn't understand this.\n");
  2948.       DeleteItem(&filebase,ip);
  2949.       }
  2950.    }
  2951.  
  2952. DeleteItemStarting(&filebase,"domain");
  2953. EditItemsInResolvConf(VRESOLVE,&filebase);
  2954. sprintf(VBUFF,"domain %s",ToLowerStr(VDOMAIN));
  2955. PrependItem(&filebase,VBUFF,NULL);
  2956.  
  2957. if (DONTDO)
  2958.    {
  2959.    printf("Check %s for editing\n",VRESOLVCONF[VSYSTEMHARDCLASS]);
  2960.    }
  2961. else if (!ItemListsEqual(filebase,referencefile))
  2962.    {
  2963.    SaveItemList(filebase,VRESOLVCONF[VSYSTEMHARDCLASS]);
  2964.    chmod(VRESOLVCONF[VSYSTEMHARDCLASS],DEFAULTSYSTEMMODE);
  2965.    }
  2966. else
  2967.    {
  2968.    Verbose("cfengine: %s is okay\n",VRESOLVCONF[VSYSTEMHARDCLASS]);
  2969.    }
  2970.  
  2971. DeleteItemList(filebase);
  2972. DeleteItemList(referencefile);
  2973. }
  2974.  
  2975.  
  2976. /*******************************************************************/
  2977.  
  2978. MakeImages()
  2979.  
  2980. { struct Image *ip;
  2981.   struct Item *svp;
  2982.   struct stat statbuf;
  2983.   struct servent *server;
  2984.   int savesilent;
  2985.  
  2986. Banner("Checking file images:");
  2987.  
  2988. if ((server = getservbyname(CFENGINE_SERVICE,"tcp")) == NULL)
  2989.    {
  2990.    CfLog(cfverbose,"Remember to register cfengine in /etc/services: cfengine 5308/tcp\n","getservbyname");
  2991.    PORTNUMBER = htons((unsigned short)5308);
  2992.    }
  2993. else
  2994.    {
  2995.    PORTNUMBER = (unsigned short)(server->s_port); /* already in network order */
  2996.    }
  2997.  
  2998. for (svp = VSERVERLIST; svp != NULL; svp=svp->next) /* order servers */
  2999.    {
  3000.    Debug("New server....\n");
  3001.    for (ip = VIMAGE; ip != NULL; ip=ip->next)
  3002.       {
  3003.       if (strcmp(svp->name,ip->server) != 0)  /* group together similar hosts so */
  3004.      {                                    /* can can do multiple transactions */
  3005.      continue;                            /* on one connection */
  3006.      }
  3007.       
  3008.       if (IsExcluded(ip->classes))
  3009.      {
  3010.      continue;
  3011.      }
  3012.  
  3013.       if (!OpenServerConnection(svp,ip))
  3014.      {
  3015.      sprintf(OUTPUT,"Unable to establish connection with %s\n",svp->name);
  3016.      CfLog(cferror,OUTPUT,"");
  3017.      continue;
  3018.      }
  3019.  
  3020.       if (AUTHENTICATED)
  3021.      {
  3022.      Debug("Authentic connection verified\n");
  3023.      }
  3024.    
  3025.       IMAGEBACKUP = true;
  3026.       
  3027.       Verbose("Checking copy from %s:%s to %s\n",ip->server,ip->path,ip->destination);
  3028.       
  3029.       savesilent = SILENT;
  3030.       
  3031.       if (strcmp(ip->action,"silent") == 0)
  3032.      {
  3033.      SILENT = true;
  3034.      }
  3035.       
  3036.       ResetOutputRoute(ip->log,ip->inform);
  3037.       
  3038.       if (!GetLock(ASUniqueName("copy"),CanonifyName(ip->destination),VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  3039.      {
  3040.      SILENT = savesilent;
  3041.      ResetOutputRoute('d','d');
  3042.      continue;
  3043.      }
  3044.       
  3045.       IMAGEBACKUP = ip->backup;
  3046.       
  3047.       if (cfstat(ip->path,&statbuf,ip) == -1)
  3048.      {
  3049.      sprintf(OUTPUT,"Can't stat %s in copy\n",ip->path);
  3050.      CfLog(cfinform,OUTPUT,"");
  3051.      ReleaseCurrentLock();
  3052.      SILENT = savesilent;
  3053.      ResetOutputRoute('d','d');
  3054.      continue;
  3055.      }
  3056.       
  3057.       if (strncmp(ip->destination,"home",4) == 0)
  3058.      {
  3059.      HOMECOPY = true;          /* Don't send home backups to repository */
  3060.      CheckHomeImages(ip);
  3061.      HOMECOPY = false;
  3062.      }
  3063.       else
  3064.      {
  3065.      if (S_ISDIR(statbuf.st_mode))
  3066.         {
  3067.         if (ip->purge == 'y')
  3068.            {
  3069.            Verbose("%s: (Destination purging enabled)\n",VPREFIX);
  3070.            }
  3071.         RecursiveImage(ip,ip->path,ip->destination,ip->recurse);
  3072.         }
  3073.      else
  3074.         {
  3075.         if (! MakeDirectoriesFor(ip->destination))
  3076.            {
  3077.            ReleaseCurrentLock();
  3078.            SILENT = savesilent;
  3079.            ResetOutputRoute('d','d');
  3080.            continue;
  3081.            }
  3082.         
  3083.         CheckImage(ip->path,ip->destination,ip);
  3084.         }
  3085.      }
  3086.       
  3087.       ReleaseCurrentLock();
  3088.       SILENT = savesilent;
  3089.       ResetOutputRoute('d','d');
  3090.       }
  3091.  
  3092.    CloseServerConnection();
  3093.    }
  3094. }
  3095.  
  3096. /*******************************************************************/
  3097.  
  3098. ConfigureInterfaces()
  3099.  
  3100. { struct Interface *ifp;
  3101.  
  3102. Banner("Checking network interfaces"); 
  3103.  
  3104. if (GetLock("netconfig",VIFDEV[VSYSTEMHARDCLASS],VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  3105.    {
  3106.    if (strlen(VNETMASK) != 0)
  3107.       {
  3108.       IfConf(VIFDEV[VSYSTEMHARDCLASS],VNETMASK,VBROADCAST);
  3109.       }
  3110.    
  3111.    SetDefaultRoute();
  3112.    ReleaseCurrentLock();   
  3113.    }
  3114.     
  3115. for (ifp = VIFLIST; ifp != NULL; ifp=ifp->next)
  3116.    {
  3117.    if (!GetLock("netconfig",ifp->ifdev,VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  3118.       {
  3119.       continue;
  3120.       }
  3121.    
  3122.    IfConf(ifp->ifdev,ifp->netmask,ifp->broadcast);
  3123.    SetDefaultRoute();
  3124.    ReleaseCurrentLock();
  3125.    }
  3126. }
  3127.  
  3128. /*******************************************************************/
  3129.  
  3130. CheckTimeZone()
  3131.  
  3132. { time_t tloc;
  3133.   struct stat statbuf;
  3134.   struct Item *ip;
  3135.   
  3136. if (VTIMEZONE == NULL)
  3137.    {
  3138.    CfLog(cferror,"Program does not define a timezone","");
  3139.    return;
  3140.    }
  3141.  
  3142. for (ip = VTIMEZONE; ip != NULL; ip=ip->next)
  3143.    {
  3144. #ifdef NT
  3145.    
  3146.    tzset();
  3147.  
  3148.    if (TZCheck(timezone(),ip->name))
  3149.       {
  3150.       return;
  3151.       }
  3152.    
  3153. #else
  3154. #ifndef AOS
  3155. #ifndef SUN4
  3156.  
  3157.    tzset();
  3158.  
  3159.    if (TZCheck(tzname[0],ip->name))
  3160.       {
  3161.       return;
  3162.       }
  3163.  
  3164. #else
  3165.  
  3166.    if ((tloc = time((time_t *)NULL)) == -1)
  3167.       {
  3168.       printf("Couldn't read system clock\n\n");
  3169.       }
  3170.    
  3171.    if (TZCheck(localtime(&tloc)->tm_zone ,ip->name))
  3172.       {
  3173.       return;
  3174.       }
  3175.    
  3176. #endif /* SUN4 */
  3177. #endif /* AOS  */
  3178. #endif /* NT */
  3179.    }
  3180.  
  3181.  
  3182. CfLog(cferror,"Time zone was not within the list of acceptable values",""); 
  3183. }
  3184.  
  3185. /*******************************************************************/
  3186.  
  3187. CheckProcesses()
  3188.  
  3189. { struct Process *pp;
  3190.   struct Item *procdata = NULL;
  3191.   char *psopts = VPSOPTS[VSYSTEMHARDCLASS];
  3192.  
  3193. Banner("Checking Processes:");
  3194.  
  3195. if (!LoadProcessTable(&procdata,psopts))
  3196.    {
  3197.    CfLog(cferror,"Unable to read the process table\n","");
  3198.    return;
  3199.    }
  3200.  
  3201. for (pp = VPROCLIST; pp != NULL; pp=pp->next)
  3202.    {
  3203.    if (IsExcluded(pp->classes))
  3204.       {
  3205.       continue;
  3206.       }
  3207.    
  3208.    ResetOutputRoute(pp->log,pp->inform);
  3209.    
  3210.    if (strcmp(pp->expr,"SetOptionString") == 0)
  3211.       {
  3212.       psopts = pp->restart;
  3213.       DeleteItemList(procdata);
  3214.       procdata = NULL;
  3215.       if (!LoadProcessTable(&procdata,psopts))
  3216.      {
  3217.      CfLog(cferror,"Unable to read the process table\n","");
  3218.      }
  3219.       }
  3220.    else
  3221.       {
  3222.       DoProcessCheck(pp,procdata);
  3223.       }
  3224.    
  3225.    ResetOutputRoute('d','d');
  3226.    }
  3227. }
  3228.  
  3229. /*******************************************************************/
  3230. /* Level 2                                                         */
  3231. /*******************************************************************/
  3232.  
  3233. CheckOpts(argc,argv)
  3234.  
  3235. char **argv;
  3236. int argc;
  3237.  
  3238. { extern char *optarg;
  3239.   int optindex = 0;
  3240.   int c;
  3241.  
  3242. while ((c=getopt_long(argc,argv,"MAbKqkhYHd:vlniIf:pPmcCtsSaeEVD:N:LwxXuU",OPTIONS,&optindex)) != EOF)
  3243.   {
  3244.   switch ((char) c)
  3245.       {
  3246.       case 'E': printf("%s: the enforce-links option can only be used in interactive mode.\n",VPREFIX);
  3247.                 printf("%s: Do you really want to blindly enforce ALL links? (y/n)\n",VPREFIX);
  3248.                 if (getchar() != 'y')
  3249.                    {
  3250.                    printf("cfengine: aborting\n");
  3251.            closelog();
  3252.                    exit(1);
  3253.                    }
  3254.  
  3255.                 ENFORCELINKS = true;
  3256.                 break;
  3257.  
  3258.       case 'f': strcpy(VINPUTFILE,optarg);
  3259.                 MINUSF = true;
  3260.                 break;
  3261.  
  3262.       case 'd': 
  3263.  
  3264.             if (optarg == NULL)
  3265.            {
  3266.            break;
  3267.            }
  3268.         
  3269.                 switch ((optarg==NULL)?3:*optarg)
  3270.                    {
  3271.                    case '1': D1 = true;
  3272.                              break;
  3273.                    case '2': D2 = true;
  3274.                              break;
  3275.            case '3': D3 = true;
  3276.                      VERBOSE = true;
  3277.                      break;
  3278.                    default:  DEBUG = true;
  3279.                              break;
  3280.                    }
  3281.                 break;
  3282.  
  3283.       case 'M':
  3284.         NOMODULES = true;
  3285.         break;
  3286.         
  3287.       case 'K': IGNORELOCK = true;
  3288.             break;
  3289.  
  3290.       case 'A': IGNORELOCK = true;
  3291.             break;
  3292.         
  3293.       case 'D': AddCompoundClass(optarg);
  3294.                 break;
  3295.  
  3296.       case 'N': NegateCompoundClass(optarg,&VNEGHEAP);
  3297.                 break;
  3298.  
  3299.       case 'b': FORCENETCOPY = true;
  3300.             break;
  3301.  
  3302.       case 'e': NOEDITS = true;
  3303.                 break;
  3304.  
  3305.       case 'i': IFCONF = false;
  3306.                 break;
  3307.  
  3308.       case 'I': INFORM = true;
  3309.             break;
  3310.  
  3311.       case 'v': VERBOSE = true;
  3312.                 break;
  3313.  
  3314.       case 'l': TRAVLINKS = true;
  3315.                 break;
  3316.  
  3317.       case 'n': DONTDO = true;
  3318.             IGNORELOCK = true;
  3319.                 break;
  3320.  
  3321.       case 'p': PARSEONLY = true;
  3322.                 IGNORELOCK = true;
  3323.                 break;
  3324.  
  3325.       case 'm': NOMOUNTS = true;
  3326.                 break;
  3327.  
  3328.       case 'c': NOFILECHECK = true;
  3329.                 break;
  3330.  
  3331.       case 'C': MOUNTCHECK = true;
  3332.                 break;
  3333.  
  3334.       case 't': NOTIDY = true;
  3335.                 break;
  3336.  
  3337.       case 's': NOSCRIPTS = true;
  3338.                 break;
  3339.  
  3340.       case 'a': PRSYSADM = true;
  3341.                 IGNORELOCK = true;
  3342.                 break;
  3343.  
  3344.       case 'L': KILLOLDLINKS = true;
  3345.                 break;
  3346.  
  3347.       case 'V': printf("GNU %s\n%s\n",VERSION,COPYRIGHT);
  3348.             printf("This program is covered by the GNU Public License and may be\n");
  3349.         printf("copied free of charge.  No warranty is implied.\n\n");
  3350.                 exit(0);
  3351.  
  3352.       case 'h': Syntax();
  3353.                 exit(0);
  3354.  
  3355.       case 'x': NOPRECONFIG = true;
  3356.                 break;
  3357.  
  3358.       case 'w': WARNINGS = false;
  3359.                 break;
  3360.  
  3361.       case 'X': NOLINKS = true;
  3362.                 break;
  3363.  
  3364.       case 'k': NOCOPY = true;
  3365.                 break;
  3366.  
  3367.       case 'S': SILENT = true;
  3368.                 break;
  3369.  
  3370.       case 'u': USEENVIRON = true;
  3371.                 break;
  3372.  
  3373.       case 'U': UNDERSCORE_CLASSES = true;
  3374.             break;
  3375.  
  3376.       case 'H': NOHARDCLASSES = true;
  3377.             break;
  3378.  
  3379.       case 'P': NOPROCS = true;
  3380.             break;
  3381.  
  3382.       case 'q': NOSPLAY = true;
  3383.             break;
  3384.  
  3385.       case 'Y': CFPARANOID = true;
  3386.             break;
  3387.  
  3388.       default:  Syntax();
  3389.                 exit(1);
  3390.  
  3391.       }
  3392.    }
  3393. }
  3394.  
  3395. /*******************************************************************/
  3396.  
  3397. GetResource(var)
  3398.  
  3399. char *var;
  3400.  
  3401. { int i;
  3402.  
  3403. for (i = 0; VRESOURCES[i] != '\0'; i++)
  3404.    {
  3405.    if (strcmp(VRESOURCES[i],var)==0)
  3406.       {
  3407.       return i;
  3408.       }
  3409.    }
  3410.  
  3411. sprintf (VBUFF,"Unknown resource %s in %s",var,VRCFILE);
  3412.  
  3413. FatalError(VBUFF);
  3414.  
  3415. return 0; /* This to placate insight */
  3416. }
  3417.  
  3418.  
  3419. /*******************************************************************/
  3420.  
  3421. ListDefinedClasses()
  3422.  
  3423. { struct Item *ptr;
  3424.  
  3425. printf ("\nDefined Classes = ( ");
  3426.  
  3427. for (ptr = VHEAP; ptr != NULL; ptr=ptr->next)
  3428.    {
  3429.    printf("%s ",ptr->name);
  3430.    }
  3431.  
  3432. printf (")\n");
  3433.  
  3434. printf ("\nNegated Classes = ( ");
  3435.  
  3436. for (ptr = VNEGHEAP; ptr != NULL; ptr=ptr->next)
  3437.    {
  3438.    printf("%s ",ptr->name);
  3439.    }
  3440.  
  3441. printf (")\n\n");
  3442.  
  3443. printf ("Installable classes = ( ");
  3444.  
  3445. for (ptr = VALLADDCLASSES; ptr != NULL; ptr=ptr->next)
  3446.    {
  3447.    printf("%s ",ptr->name);
  3448.    }
  3449.  
  3450. printf (")\n");
  3451.  
  3452. if (VEXCLUDECOPY != NULL)
  3453.    {
  3454.    printf("Patterns to exclude from copies: = (");
  3455.    
  3456.    for (ptr = VEXCLUDECOPY; ptr != NULL; ptr=ptr->next)
  3457.       {
  3458.       printf("%s ",ptr->name);
  3459.       }
  3460.  
  3461.    printf (")\n");
  3462.    }
  3463.  
  3464. if (VEXCLUDELINK != NULL)
  3465.    {
  3466.    printf("Patterns to exclude from links: = (");
  3467.    
  3468.    for (ptr = VEXCLUDELINK; ptr != NULL; ptr=ptr->next)
  3469.       {
  3470.       printf("%s ",ptr->name);
  3471.       }
  3472.  
  3473.    printf (")\n");
  3474.    }
  3475.  
  3476. if (VCOPYLINKS != NULL)
  3477.    {
  3478.    printf("Patterns to copy instead of link: = (");
  3479.    
  3480.    for (ptr = VCOPYLINKS; ptr != NULL; ptr=ptr->next)
  3481.       {
  3482.       printf("%s ",ptr->name);
  3483.       }
  3484.  
  3485.    printf (")\n");
  3486.    }
  3487.  
  3488. if (VCOPYLINKS != NULL)
  3489.    {
  3490.    printf("Patterns to link instead of copy: = (");
  3491.    
  3492.    for (ptr = VLINKCOPIES; ptr != NULL; ptr=ptr->next)
  3493.       {
  3494.       printf("%s ",ptr->name);
  3495.       }
  3496.  
  3497.    printf (")\n");
  3498.    }
  3499.  
  3500. }
  3501.  
  3502. /*********************************************************************/
  3503.  
  3504. ListDefinedInterfaces()
  3505.  
  3506. { struct Interface *ifp;
  3507.  
  3508.  printf ("\nDEFINED INTERFACES\n\n");
  3509.  
  3510. for (ifp = VIFLIST; ifp !=NULL; ifp=ifp->next)
  3511.    {
  3512.    printf("Interface %s, netmask=%s, broadcast=%s\n",ifp->ifdev,ifp->netmask,ifp->broadcast);
  3513.    }
  3514. }
  3515.  
  3516. /*********************************************************************/
  3517.  
  3518. ListDefinedHomePatterns()
  3519.  
  3520. { struct Item *ptr;
  3521.  
  3522.  
  3523. printf ("\nDefined wildcards to match home directories = ( ");
  3524.  
  3525. for (ptr = VHOMEPATLIST; ptr != NULL; ptr=ptr->next)
  3526.    {
  3527.    printf("%s ",ptr->name);
  3528.    }
  3529.  
  3530. printf (")\n");
  3531. }
  3532.  
  3533. /*********************************************************************/
  3534.  
  3535. ListDefinedBinservers()
  3536.  
  3537. { struct Item *ptr;
  3538.  
  3539. printf ("\nDefined Binservers = ( ");
  3540.  
  3541. for (ptr = VBINSERVERS; ptr != NULL; ptr=ptr->next)
  3542.    {
  3543.    printf("%s ",ptr->name);
  3544.    }
  3545.  
  3546. printf (")\n");
  3547. }
  3548.  
  3549. /*********************************************************************/
  3550.  
  3551. ListDefinedLinks()
  3552.  
  3553. { struct Link *ptr;
  3554.   struct Item *ip;
  3555.   
  3556. printf ("\nDEFINED LINKS\n\n");
  3557.  
  3558. for (ptr = VLINK; ptr != NULL; ptr=ptr->next)
  3559.    {
  3560.    printf("From %s -> %s force=%d, attr=%d type=%c nofile=%d\n",ptr->from,ptr->to,ptr->force,ptr->silent,ptr->type, ptr->nofile);
  3561.    for (ip = ptr->copy; ip != NULL; ip = ip->next)
  3562.       {
  3563.       printf(" Copy %s\n",ip->name);
  3564.       }
  3565.  
  3566.    for (ip = ptr->exclusions; ip != NULL; ip = ip->next)
  3567.       {
  3568.       printf(" Exclude %s\n",ip->name);
  3569.       }
  3570.  
  3571.    for (ip = ptr->inclusions; ip != NULL; ip = ip->next)
  3572.       {
  3573.       printf(" Include %s\n",ip->name);
  3574.       }
  3575.  
  3576.    for (ip = ptr->ignores; ip != NULL; ip = ip->next)
  3577.       {
  3578.       printf(" Ignore %s\n",ip->name);
  3579.       }
  3580.  
  3581.    printf(" Define %s\n",ptr->defines);
  3582.    }
  3583. }
  3584.  
  3585. /*********************************************************************/
  3586.  
  3587. ListDefinedLinkchs()
  3588.  
  3589. { struct Link *ptr;
  3590.   struct Item *ip;
  3591.  
  3592. printf ("\nDEFINED CHILD LINKS\n\n");
  3593.  
  3594. for (ptr = VCHLINK; ptr != NULL; ptr=ptr->next)
  3595.    {
  3596.    printf("[%s->%s] force=%d attr=%d, rec=%d\n",ptr->from,ptr->to,
  3597.       ptr->force,ptr->silent,ptr->recurse);
  3598.    
  3599.    for (ip = ptr->copy; ip != NULL; ip = ip->next)
  3600.       {
  3601.       printf(" Copy %s\n",ip->name);
  3602.       }
  3603.  
  3604.    for (ip = ptr->exclusions; ip != NULL; ip = ip->next)
  3605.       {
  3606.       printf(" Exclude %s\n",ip->name);
  3607.       }
  3608.    
  3609.    for (ip = ptr->inclusions; ip != NULL; ip = ip->next)
  3610.       {
  3611.       printf(" Include %s\n",ip->name);
  3612.       }
  3613.  
  3614.    for (ip = ptr->ignores; ip != NULL; ip = ip->next)
  3615.       {
  3616.       printf(" Ignore %s\n",ip->name);
  3617.       }
  3618.  
  3619.    printf(" Define %s\n",ptr->defines);
  3620.    }
  3621. }
  3622.  
  3623. /*********************************************************************/
  3624.  
  3625. ListDefinedResolvers()
  3626.  
  3627. { struct Item *ptr;
  3628.  
  3629. printf ("\nDEFINED NAMESERVERS\n\n");
  3630.  
  3631. for (ptr = VRESOLVE; ptr != NULL; ptr=ptr->next)
  3632.    {
  3633.    printf("%s\n",ptr->name);
  3634.    }
  3635.  
  3636. printf (")\n");
  3637. }
  3638.  
  3639. /*********************************************************************/
  3640.  
  3641. ListDefinedScripts()
  3642.  
  3643. { struct ShellComm *ptr;
  3644.  
  3645. printf ("\nDEFINED SHELLCOMMANDS\n\n");
  3646.  
  3647. for (ptr = VSCRIPT; ptr != NULL; ptr=ptr->next)
  3648.    {
  3649.    printf("%s: timeout=%d,uid=%d,gid=%d\n",ptr->name,ptr->timeout,ptr->uid,ptr->gid);
  3650.    }
  3651. }
  3652.  
  3653. /*********************************************************************/
  3654.  
  3655. ListDefinedImages()
  3656.  
  3657. { struct Image *ptr;
  3658.   struct UidList *up;
  3659.   struct GidList *gp;
  3660.   struct Item *iip, *svp;
  3661.   struct sockaddr_in raddr;
  3662.   
  3663. printf ("\nDEFINED FILE IMAGES\n\n");
  3664.  
  3665. for (svp = VSERVERLIST; svp != NULL; svp=svp->next) /* order servers */
  3666.    {
  3667.    for (ptr = VIMAGE; ptr != NULL; ptr=ptr->next)
  3668.       {
  3669.       if (strcmp(svp->name,ptr->server) != 0)  /* group together similar hosts so */
  3670.      {                                  /* can can do multiple transactions */
  3671.      continue;                          /* on one connection */
  3672.      } 
  3673.       
  3674.       printf("\n%s\n +%o\n -%o\n dest: %s\n action: %s\n",ptr->path,ptr->plus,ptr->minus,
  3675.          ptr->destination,ptr->action);
  3676.       
  3677.       printf(" Size %c %d\n",ptr->comp,ptr->size);
  3678.       
  3679.       if (ptr->recurse == INFINITERECURSE)
  3680.      {
  3681.      printf(" recurse=inf\n");
  3682.      }
  3683.       else
  3684.      {
  3685.      printf(" recurse=%d\n",ptr->recurse);
  3686.      }
  3687.       
  3688.       printf(" uids = ( ");
  3689.       
  3690.       for (up = ptr->uid; up != NULL; up=up->next)
  3691.      {
  3692.      printf("%d ",up->uid);
  3693.      }
  3694.       
  3695.       printf(")\n gids = ( ");
  3696.       
  3697.       for (gp = ptr->gid; gp != NULL; gp=gp->next)
  3698.      {
  3699.      printf("%d ",gp->gid);
  3700.      }
  3701.       
  3702.       printf(")\n\n exclude:");
  3703.       
  3704.       for (iip = ptr->acl_aliases; iip != NULL; iip=iip->next)
  3705.      {
  3706.      printf(" ACL object %s\n",iip->name);
  3707.      }
  3708.       
  3709.       printf("ignore:");
  3710.       
  3711.       for (iip = ptr->ignores; iip != NULL; iip = iip->next)
  3712.      {
  3713.      printf(" %s",iip->name);
  3714.      }
  3715.       
  3716.       printf("\n");
  3717.       printf(" symlink:");
  3718.       
  3719.       for (iip = ptr->symlink; iip != NULL; iip = iip->next)
  3720.      {
  3721.      printf(" %s",iip->name);
  3722.      }
  3723.       
  3724.       printf("\n include:");
  3725.       
  3726.       for (iip = ptr->inclusions; iip != NULL; iip = iip->next)
  3727.      {
  3728.      printf(" %s",iip->name);
  3729.      }
  3730.       printf("\n");
  3731.       
  3732.       printf(" classes = %s\n",ptr->classes);
  3733.       
  3734.       printf(" method = %c (time/checksum)\n",ptr->type);
  3735.       
  3736.       printf(" server = %s (secure=%d)\n",ptr->server,ptr->secure);
  3737.       
  3738.       printf(" purging = %c\n",ptr->purge);
  3739.       
  3740.       if (ptr->dns != NULL)
  3741.      {
  3742.      raddr.sin_addr.s_addr = (ptr->dns)->s_addr;
  3743.      printf(" host entry cache = %d = %s\n",ptr->dns,inet_ntoa(raddr.sin_addr));
  3744.      }
  3745.       
  3746.       printf(" define = %s\n",ptr->defines);
  3747.       
  3748.       if (! ptr->backup)
  3749.      {
  3750.      printf(" NOT BACKED UP\n");
  3751.      }
  3752.       
  3753.       if (ptr->stealth == 't')
  3754.      {
  3755.      printf(" Stealth copy\n");
  3756.      }
  3757.       }
  3758.    }
  3759. }
  3760.  
  3761. /*********************************************************************/
  3762.  
  3763. ListDefinedTidy()
  3764.  
  3765. { struct Tidy *ptr;
  3766.   struct TidyPattern *tp;
  3767.  
  3768. printf ("\nDEFINED TIDY MASKS\n\n");
  3769.  
  3770. for (ptr = VTIDY; ptr != NULL; ptr=ptr->next)
  3771.    {
  3772.    printf("  path=[%s]\n",ptr->path);
  3773.    
  3774.    for(tp = ptr->tidylist; tp != NULL; tp=tp->next)
  3775.       {
  3776.       printf("    pat=%s, define=%s, %c-age=%d, size=%d, linkdirs=%c, rmdirs=%c, travlinks=%c ",
  3777.          tp->pattern,tp->defines,tp->searchtype,tp->age,tp->size,tp->dirlinks,tp->rmdirs,tp->travlinks);
  3778.  
  3779.       if (tp->recurse == INFINITERECURSE)
  3780.      {
  3781.      printf("recurse=inf\n");
  3782.      }
  3783.       else
  3784.      {
  3785.      printf("recurse=%d\n",tp->recurse);
  3786.      }
  3787.       }
  3788.    }
  3789. }
  3790.  
  3791. /*********************************************************************/
  3792.  
  3793. ListDefinedMountables()
  3794.  
  3795. { struct Item *ptr;
  3796.  
  3797. printf ("\nDEFINED MOUNTABLES\n\n");
  3798.  
  3799. for (ptr = VMOUNTABLES; ptr != NULL; ptr=ptr->next)
  3800.    {
  3801.    printf("%s\n",ptr->name);
  3802.    }
  3803. }
  3804.  
  3805. /*********************************************************************/
  3806.  
  3807. ListMiscMounts()
  3808.  
  3809. { struct MiscMount *ptr;
  3810.  
  3811. printf ("\nDEFINED MISC MOUNTABLES\n\n");
  3812.  
  3813. for (ptr = VMISCMOUNT; ptr != NULL; ptr=ptr->next)
  3814.    {
  3815.    printf("%s on %s (%s)\n",ptr->from,ptr->onto,ptr->options);
  3816.    }
  3817.  
  3818. printf (")\n");
  3819. }
  3820.  
  3821. /*********************************************************************/
  3822.  
  3823. ListDefinedRequired()
  3824.  
  3825. { struct Disk *ptr;
  3826.  
  3827. printf ("\nDEFINED REQUIRE\n\n");
  3828.  
  3829. for (ptr = VREQUIRED; ptr != NULL; ptr=ptr->next)
  3830.    {
  3831.    printf("%s, freespace=%d, define=%s\n",ptr->name,ptr->freespace,ptr->define);
  3832.    }
  3833. }
  3834.  
  3835. /*********************************************************************/
  3836.  
  3837. ListDefinedHomeservers()
  3838.  
  3839. { struct Item *ptr;
  3840.  
  3841. printf ("\nDefined home servers = ( ");
  3842.  
  3843. for (ptr = VHOMESERVERS; ptr != NULL; ptr=ptr->next)
  3844.    {
  3845.    printf("%s ",ptr->name);
  3846.    }
  3847.  
  3848. printf (")\n");
  3849. }
  3850.  
  3851. /*********************************************************************/
  3852.  
  3853. ListDefinedDisable()
  3854.  
  3855. { struct Disable *ptr;
  3856.  
  3857. printf ("\nDEFINED DISABLE\n\n");
  3858.  
  3859. for (ptr = VDISABLELIST; ptr != NULL; ptr=ptr->next)
  3860.    {
  3861.    printf("%s: rotate=%d, type=%s, size%c%d, defines=%s\n",
  3862.       ptr->name,ptr->rotate,ptr->type,ptr->comp,ptr->size,ptr->defines);
  3863.    }
  3864. }
  3865.  
  3866. /*********************************************************************/
  3867.  
  3868. ListDefinedMakePaths()
  3869.  
  3870. { struct File *ptr;
  3871.   struct UidList *up;
  3872.   struct GidList *gp;
  3873.   struct Item *ip;
  3874.   
  3875. printf ("\nDEFINED DIRECTORIES\n\n");
  3876.  
  3877. for (ptr = VMAKEPATH; ptr != NULL; ptr=ptr->next)
  3878.    {
  3879.    printf("%s\n +%o\n -%o\n %s\n",ptr->path,ptr->plus,ptr->minus,FILEACTIONTEXT[ptr->action]);
  3880.  
  3881.    if (ptr->recurse == INFINITERECURSE)
  3882.       {
  3883.       printf(" recurse=inf\n");
  3884.       }
  3885.    else
  3886.       {
  3887.       printf(" recurse=%d\n",ptr->recurse);
  3888.       }
  3889.    
  3890.    printf(" uids = ( ");
  3891.  
  3892.    for (up = ptr->uid; up != NULL; up=up->next)
  3893.       {
  3894.       printf("%d ",up->uid);
  3895.       }
  3896.  
  3897.    printf(")\n gids = ( ");
  3898.  
  3899.    for (gp = ptr->gid; gp != NULL; gp=gp->next)
  3900.       {
  3901.       printf("%d ",gp->gid);
  3902.       }
  3903.    printf(")\n\n");
  3904.  
  3905.    for (ip = ptr->acl_aliases; ip != NULL; ip=ip->next)
  3906.       {
  3907.       printf(" ACL object %s\n",ip->name);
  3908.       }
  3909.  
  3910.    printf(" define = %s\n",ptr->defines);
  3911.    }
  3912. }
  3913.  
  3914. /*********************************************************************/
  3915.  
  3916. ListDefinedImports()
  3917.  
  3918. { struct Item *ptr;
  3919.  
  3920. printf ("\nDEFINED IMPORTS\n\n");
  3921.  
  3922. for (ptr = VIMPORT; ptr != NULL; ptr=ptr->next)
  3923.    {
  3924.    printf("%s\n",ptr->name);
  3925.    }
  3926. }
  3927.  
  3928. /*********************************************************************/
  3929.  
  3930. ListDefinedIgnore()
  3931.  
  3932. { struct Item *ptr;
  3933.  
  3934. printf ("\nDEFINED IGNORE\n\n");
  3935.  
  3936. for (ptr = VIGNORE; ptr != NULL; ptr=ptr->next)
  3937.    {
  3938.    printf("%s\n",ptr->name);
  3939.    }
  3940. }
  3941.  
  3942. /*********************************************************************/
  3943.  
  3944. ListFiles()
  3945.  
  3946. { struct File *ptr;
  3947.   struct Item *ip;
  3948.   struct UidList *up;
  3949.   struct GidList *gp;
  3950.  
  3951. printf ("\nDEFINED FILES\n\n");
  3952.  
  3953. for (ptr = VFILE; ptr != NULL; ptr=ptr->next)
  3954.    {
  3955.    printf("\n%s\n +%o\n -%o\n +%o\n -%o\n %s\n travelinks=%c\n",
  3956.       ptr->path,ptr->plus,ptr->minus,ptr->plus_flags,ptr->minus_flags,
  3957.       FILEACTIONTEXT[ptr->action],ptr->travlinks);
  3958.    
  3959.    if (ptr->recurse == INFINITERECURSE)
  3960.       {
  3961.       printf(" recurse=inf\n");
  3962.       }
  3963.    else
  3964.       {
  3965.       printf(" recurse=%d\n",ptr->recurse);
  3966.       }
  3967.    
  3968.    printf(" uids = ( ");
  3969.  
  3970.    for (up = ptr->uid; up != NULL; up=up->next)
  3971.       {
  3972.       printf("%d ",up->uid);
  3973.       }
  3974.  
  3975.    printf(")\n gids = ( ");
  3976.  
  3977.    for (gp = ptr->gid; gp != NULL; gp=gp->next)
  3978.       {
  3979.       printf("%d ",gp->gid);
  3980.       }
  3981.    printf(")\n\n");
  3982.  
  3983.  
  3984.    for (ip = ptr->acl_aliases; ip != NULL; ip=ip->next)
  3985.       {
  3986.       printf(" ACL object %s\n",ip->name);
  3987.       }
  3988.       
  3989.    for (ip = ptr->exclusions; ip != NULL; ip = ip->next)
  3990.       {
  3991.       printf(" Exclude %s\n",ip->name);
  3992.       }
  3993.  
  3994.    for (ip = ptr->inclusions; ip != NULL; ip = ip->next)
  3995.       {
  3996.       printf(" Include %s\n",ip->name);
  3997.       }
  3998.  
  3999.    for (ip = ptr->ignores; ip != NULL; ip = ip->next)
  4000.       {
  4001.       printf(" Ignore %s\n",ip->name);
  4002.       }
  4003.    
  4004.    printf(" define = %s\n",ptr->defines);
  4005.    }
  4006. }
  4007.  
  4008. /*******************************************************************/
  4009.  
  4010. ListActionSequence()
  4011.  
  4012. { struct Item *ptr;
  4013.  
  4014. printf("\nAction sequence = (");
  4015.  
  4016. for (ptr=VACTIONSEQ; ptr!=NULL; ptr=ptr->next)
  4017.    {
  4018.    printf("%s ",ptr->name);
  4019.    }
  4020.  
  4021. printf(")\n");
  4022. }
  4023.  
  4024. /*******************************************************************/
  4025.  
  4026. ListUnmounts()
  4027.  
  4028. { struct UnMount *ptr;
  4029.  
  4030. printf("\nDEFINED UNMOUNTS\n\n");
  4031.  
  4032. for (ptr=VUNMOUNT; ptr!=NULL; ptr=ptr->next)
  4033.    {
  4034.    printf("%s (classes=%s) deletedir=%c deletefstab=%c force=%c\n",ptr->name,ptr->classes,ptr->deletedir,ptr->deletefstab,ptr->force);
  4035.    }
  4036. }
  4037.  
  4038. /*******************************************************************/
  4039.  
  4040. ListProcesses()
  4041.  
  4042. { struct Process *ptr;
  4043.   struct Item *ip; 
  4044.   char *sp;
  4045.  
  4046. printf("\nDEFINED PROCESSES\n\n");
  4047.  
  4048. for (ptr = VPROCLIST; ptr != NULL; ptr=ptr->next)
  4049.    {
  4050.    if (ptr->restart == NULL)
  4051.       {
  4052.       sp = "";
  4053.       }
  4054.    else
  4055.       {
  4056.       sp = ptr->restart;
  4057.       }
  4058.    
  4059.    printf("%s\n Restart = %s (useshell=%c)\n matches: %c%d\n signal=%s\n action=%c\n define=%s\n\n",
  4060.       ptr->expr,sp,ptr->useshell,ptr->comp,ptr->matches,SIGNALS[ptr->signal],ptr->action,ptr->defines);
  4061.  
  4062.    for (ip = ptr->exclusions; ip != NULL; ip = ip->next)
  4063.       {
  4064.       printf(" Exclude %s\n",ip->name);
  4065.       }
  4066.  
  4067.    for (ip = ptr->inclusions; ip != NULL; ip = ip->next)
  4068.       {
  4069.       printf(" Include %s\n",ip->name);
  4070.       }
  4071.    }
  4072.  
  4073. printf(")\n");
  4074. }
  4075.  
  4076. /*******************************************************************/
  4077.  
  4078. ListACLs()
  4079.  
  4080. { struct CFACL *ptr;
  4081.   struct CFACE *ep;
  4082.  
  4083. printf("\nDEFINED ACCESS CONTROL LISTS\n\n");
  4084.  
  4085. for (ptr = VACLLIST; ptr != NULL; ptr=ptr->next)
  4086.    {
  4087.    printf("%s (type=%d,method=%c)\n",ptr->acl_alias,ptr->type,ptr->method);
  4088.    
  4089.    for (ep = ptr->aces; ep != NULL; ep=ep->next)
  4090.       {
  4091.       if (ep->name != NULL)
  4092.          {
  4093.          printf(" Type = %s, obj=%s, mode=%s (classes=%s)\n",ep->acltype,ep->name,ep->mode,ep->classes);
  4094.          }
  4095.       }
  4096.    printf("\n");
  4097.    }
  4098.  
  4099. }
  4100.  
  4101. /*******************************************************************/
  4102.  
  4103. ListFileEdits()
  4104.  
  4105. { struct Edit *ptr;
  4106.   struct Edlist *ep;
  4107.  
  4108. printf("\nDEFINED FILE EDITS\n\n");
  4109.  
  4110. for (ptr=VEDITLIST; ptr!=NULL; ptr=ptr->next)
  4111.    {
  4112.    printf("%s\n",ptr->fname);
  4113.    for (ep = ptr->actions; ep != NULL; ep=ep->next)
  4114.       {
  4115.       if (ep->data == NULL)
  4116.          {
  4117.          printf(" %s [nodata]\n",VEDITNAMES[ep->code]);
  4118.          }
  4119.       else
  4120.          {
  4121.          printf(" %s [%s]\n",VEDITNAMES[ep->code],ep->data);
  4122.          }
  4123.       }
  4124.    printf("\n");
  4125.    }
  4126. }
  4127.  
  4128. /*******************************************************************/
  4129.  
  4130. BuildClassEnvironment()
  4131.  
  4132. { struct Item *ip;
  4133.  
  4134. sprintf(ALLCLASSBUFFER,"%s=\0",CFALLCLASSESVAR);
  4135.  
  4136. for (ip = VHEAP; ip != NULL; ip=ip->next)
  4137.    {
  4138.    if (IsDefinedClass(ip->name))
  4139.       {
  4140.       if (BufferOverflow(ALLCLASSBUFFER,ip->name))
  4141.      {
  4142.      printf("%s: culprit BuildClassEnvironment()\n",VPREFIX);
  4143.      return;
  4144.      }
  4145.  
  4146.       strcat(ALLCLASSBUFFER,ip->name);
  4147.       strcat(ALLCLASSBUFFER,":");
  4148.       }
  4149.    }
  4150.  
  4151. for (ip = VALLADDCLASSES; ip != NULL; ip=ip->next)
  4152.    {
  4153.    if (IsDefinedClass(ip->name))
  4154.       {
  4155.       if (BufferOverflow(ALLCLASSBUFFER,ip->name))
  4156.      {
  4157.      printf("%s: culprit BuildClassEnvironment()\n",VPREFIX);
  4158.      return;
  4159.      }
  4160.       
  4161.       strcat(ALLCLASSBUFFER,ip->name);
  4162.       strcat(ALLCLASSBUFFER,":");
  4163.       }
  4164.    }
  4165.  
  4166. Debug2("---\nENVIRONMENT: %s\n---\n",ALLCLASSBUFFER);
  4167.  
  4168. if (USEENVIRON)
  4169.    {
  4170.    if (putenv(ALLCLASSBUFFER) == -1)
  4171.       {
  4172.       perror("putenv");
  4173.       }
  4174.    }
  4175. }
  4176.  
  4177. /*******************************************************************/
  4178.  
  4179. CheckForModule(actiontxt)
  4180.  
  4181. char *actiontxt;
  4182.  
  4183. { struct stat statbuf;
  4184.   char *sp, line[bufsize], id[maxvarsize], *value;
  4185.   FILE *pp;
  4186.   int print;
  4187.  
  4188. if (NOMODULES)
  4189.    {
  4190.    return;
  4191.    }
  4192.   
  4193. bzero(VBUFF,bufsize);
  4194.  
  4195. if (GetMacroValue("moduledirectory"))
  4196.    {
  4197.    ExpandVarstring("$(moduledirectory)",VBUFF,NULL);
  4198.    }
  4199. else
  4200.    {
  4201.    sprintf(OUTPUT,"Plugin was called in ActionSequence but moduledirectory was not defined\n");
  4202.    CfLog(cfinform,OUTPUT,"");
  4203.    return;
  4204.    }
  4205.  
  4206. AddSlash(VBUFF);
  4207. strcat(VBUFF,actiontxt);
  4208.  
  4209. if (stat(VBUFF,&statbuf) == -1)
  4210.    {
  4211.    sprintf(OUTPUT,"(Plug-in %s not found)",VBUFF);
  4212.    Banner(OUTPUT);
  4213.    return;
  4214.    }
  4215.  
  4216. if ((statbuf.st_uid != 0) && (statbuf.st_uid != getuid()))
  4217.    {
  4218.    sprintf(OUTPUT,"Module %s was not owned by uid=%d executing cfengine\n",VBUFF,getuid());
  4219.    CfLog(cferror,OUTPUT,"");
  4220.    return;
  4221.    }
  4222.  
  4223. sprintf(OUTPUT,"Plug-in `%s\'",actiontxt);
  4224. Banner(OUTPUT);
  4225.  
  4226. if (!GetLock(ASUniqueName("actionseq"),CanonifyName(actiontxt),VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  4227.    {
  4228.    return;
  4229.    }
  4230.    
  4231. if ((pp = cfpopen(VBUFF,"r")) == NULL)
  4232.    {
  4233.    sprintf(OUTPUT,"Couldn't open pipe from %s\n",actiontxt);
  4234.    CfLog(cferror,OUTPUT,"cfpopen");
  4235.    return;
  4236.    }
  4237.  
  4238. while (!feof(pp))
  4239.    {
  4240.    if (ferror(pp))  /* abortable */
  4241.       {
  4242.       sprintf(OUTPUT,"Shell command pipe %s\n",actiontxt);
  4243.       CfLog(cferror,OUTPUT,"ferror");
  4244.       break;
  4245.       }
  4246.    
  4247.    ReadLine(line,bufsize,pp);
  4248.  
  4249.    if (strlen(line) > maxvarsize)
  4250.       {
  4251.       sprintf(OUTPUT,"Line from module %s is too long to be sensible\n",actiontxt);
  4252.       CfLog(cferror,OUTPUT,"");
  4253.       break;
  4254.       }
  4255.    
  4256.    if (ferror(pp))  /* abortable */
  4257.       {
  4258.       sprintf(OUTPUT,"Shell command pipe %s\n",actiontxt);
  4259.       CfLog(cferror,OUTPUT,"ferror");
  4260.       break;
  4261.       }     
  4262.    
  4263.    print = false;
  4264.    
  4265.    for (sp = line; *sp != '\0'; sp++)
  4266.       {
  4267.       if (! isspace(*sp))
  4268.      {
  4269.      print = true;
  4270.      break;
  4271.      }
  4272.       }
  4273.    
  4274.    switch (*line)
  4275.       {
  4276.       case '+':
  4277.       Verbose("Activated classes: %s\n",line+1);
  4278.       AddMultipleClasses(line+1);
  4279.       break;
  4280.       case '-':
  4281.       Verbose("Deactivated classes: %s\n",line+1);
  4282.       NegateCompoundClass(line+1,&VNEGHEAP);
  4283.       break;
  4284.  
  4285.       default:
  4286.       if (print)
  4287.          {
  4288.          printf("%s:%s: %s\n",VPREFIX,actiontxt,line);
  4289.          }
  4290.       }
  4291.    }
  4292.  
  4293. cfpclose(pp);
  4294.  
  4295. ReleaseCurrentLock();
  4296. }
  4297.  
  4298.  
  4299. /*******************************************************************/
  4300.  
  4301. RequiredFileSystemOkay (name)
  4302.  
  4303. char *name;
  4304.  
  4305. { struct stat statbuf, localstat;
  4306.   DIR *dirh;
  4307.   struct dirent *dirp;
  4308.   long sizeinbytes = 0, filecount = 0;
  4309.   char buff[bufsize];
  4310.  
  4311. Debug2("Checking required filesystem %s\n",name);
  4312.  
  4313. if (stat(name,&statbuf) == -1)
  4314.    {
  4315.    return(false);
  4316.    }
  4317.  
  4318. if (S_ISLNK(statbuf.st_mode))
  4319.    {
  4320.    KillOldLink(name);
  4321.    return(true);
  4322.    }
  4323.  
  4324. if (S_ISDIR(statbuf.st_mode))
  4325.    {
  4326.    if ((dirh = opendir(name)) == NULL)
  4327.       {
  4328.       sprintf(OUTPUT,"Can't open directory %s which checking required/disk\n",name);
  4329.       CfLog(cferror,OUTPUT,"opendir");
  4330.       return false;
  4331.       }
  4332.  
  4333.    for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
  4334.       {
  4335.       if (!SensibleFile(dirp->d_name,name,NULL))
  4336.          {
  4337.          continue;
  4338.          }
  4339.  
  4340.       filecount++;
  4341.  
  4342.       strcpy(buff,name);
  4343.  
  4344.       if (buff[strlen(buff)] != '/')
  4345.          {
  4346.          strcat(buff,"/");
  4347.          }
  4348.  
  4349.       strcat(buff,dirp->d_name);
  4350.  
  4351.       if (lstat(buff,&localstat) == -1)
  4352.          {
  4353.          if (S_ISLNK(localstat.st_mode))
  4354.             {
  4355.             KillOldLink(buff);
  4356.             continue;
  4357.             }
  4358.  
  4359.          sprintf(OUTPUT,"Can't stat %s in required/disk\n",buff);
  4360.      CfLog(cferror,OUTPUT,"lstat");
  4361.          continue;
  4362.          }
  4363.  
  4364.       sizeinbytes += localstat.st_size;
  4365.       }
  4366.  
  4367.    closedir(dirh);
  4368.  
  4369.    if (sizeinbytes < 0)
  4370.       {
  4371.       Verbose("Internal error: count of byte size was less than zero!\n");
  4372.       return true;
  4373.       }
  4374.  
  4375.    if (sizeinbytes < SENSIBLEFSSIZE)
  4376.       {
  4377.       sprintf(OUTPUT,"File system %s is suspiciously small! (%d bytes)\n",name,sizeinbytes);
  4378.       CfLog(cferror,OUTPUT,"");
  4379.       return(true);
  4380.       }
  4381.  
  4382.    if (filecount < SENSIBLEFILECOUNT)
  4383.       {
  4384.       sprintf(OUTPUT,"Filesystem %s has only %d files/directories.\n",name,filecount);
  4385.       CfLog(cferror,OUTPUT,"");
  4386.       return(true);
  4387.       }
  4388.    }
  4389.  
  4390. return(true);
  4391. }
  4392.  
  4393.  
  4394. /*******************************************************************/
  4395.  
  4396. InstallMountedItem(host,mountdir)
  4397.  
  4398. char *host, *mountdir;
  4399.  
  4400. {
  4401. strcpy (VBUFF,host);
  4402. strcat (VBUFF,":");
  4403. strcat (VBUFF,mountdir);
  4404.  
  4405. if (IsItemIn(VMOUNTED,VBUFF))
  4406.    {
  4407.    if (! SILENT || !WARNINGS)
  4408.       {
  4409.       sprintf(OUTPUT,"WARNING mount item %s\n",VBUFF);
  4410.       CfLog(cferror,OUTPUT,"");
  4411.       CfLog(cferror,"is mounted multiple times!\n","");
  4412.       }
  4413.    }
  4414.  
  4415. AppendItem(&VMOUNTED,VBUFF,NULL);
  4416. }
  4417.  
  4418. /*******************************************************************/
  4419.  
  4420.  
  4421. AddToFstab(host,rmountpt,mountpt,mode,ismounted)
  4422.  
  4423. char *host, *mountpt, *rmountpt, *mode;
  4424. int ismounted;
  4425.  
  4426. { char fstab[bufsize];
  4427.   char *opts;
  4428.   FILE *fp;
  4429.  
  4430. Debug("AddToFstab(%s)\n",mountpt);
  4431.  
  4432. opts = VMOUNTOPTS[VSYSTEMHARDCLASS];
  4433.  
  4434. switch (VSYSTEMHARDCLASS)
  4435.    {
  4436.    case osf:
  4437.    case bsd4_3:
  4438.    case irix:
  4439.    case irix4:
  4440.    case irix64:
  4441.    case sun3:
  4442.    case aos:
  4443.    case nextstep:
  4444.    case newsos:
  4445.    case sun4:    sprintf(fstab,"%s:%s \t %s %s\t%s,%s 0 0",host,rmountpt,mountpt,VNFSTYPE,mode,opts);
  4446.                  break;
  4447.  
  4448.    case crayos:
  4449.                  sprintf(fstab,"%s:%s \t %s %s\t%s,%s",host,rmountpt,mountpt,ToUpperStr(VNFSTYPE),mode,opts);
  4450.                  break;
  4451.    case ultrx:   sprintf(fstab,"%s@%s:%s:%s:0:0:%s:%s",rmountpt,host,mountpt,mode,VNFSTYPE,opts);
  4452.                  break;
  4453.    case hp10:
  4454.    case hp:      sprintf(fstab,"%s:%s %s \t %s \t %s,%s 0 0",host,rmountpt,mountpt,VNFSTYPE,mode,opts);
  4455.                  break;
  4456.    case aix:     sprintf(fstab,"%s:\n\tdev\t= %s\n\ttype\t= %s\n\tvfs\t= %s\n\tnodename\t= %s\n\tmount\t= true\n\toptions\t= %s,%s\n\taccount\t= false\n\n",mountpt,rmountpt,VNFSTYPE,VNFSTYPE,host,mode,opts);
  4457.                  break;
  4458.    case GnU:
  4459.    case linuxx:  sprintf(fstab,"%s:%s \t %s \t %s \t %s",host,rmountpt,mountpt,VNFSTYPE,opts);
  4460.                  break;
  4461.  
  4462.    case netbsd:
  4463.    case openbsd:
  4464.    case bsd_i:
  4465.    case freebsd: sprintf(fstab,"%s:%s \t %s \t %s \t %s,%s 0 0",host,rmountpt,mountpt,VNFSTYPE,mode,opts);
  4466.                  break;
  4467.  
  4468.    case unix_sv:
  4469.    case solarisx86:
  4470.    case solaris: sprintf(fstab,"%s:%s - %s %s - yes %s,%s",host,rmountpt,mountpt,VNFSTYPE,mode,opts);
  4471.                  break;
  4472.  
  4473.    case cfnt:    sprintf(fstab,"/bin/mount %s:%s %s",host,rmountpt,mountpt);
  4474.                  break;
  4475.    case cfsco:   CfLog(cferror,"Don't understand filesystem format on SCO, no data","");
  4476.                  break;
  4477.    case unused1:
  4478.    case unused2:
  4479.    case unused3:
  4480.    default:      FatalError("AddToFstab(): unknown hard class detected!\n");
  4481.                  break;
  4482.    }
  4483.  
  4484. if (MatchStringInFstab(mountpt))
  4485.    {
  4486.    if (!ismounted && !SILENT && !strstr(mountpt,"cdrom"))
  4487.       {
  4488.       sprintf(OUTPUT,"Warning the file system %s seems to be in %s\n",mountpt,VFSTAB[VSYSTEMHARDCLASS]);
  4489.       CfLog(cfinform,OUTPUT,"");
  4490.       sprintf(OUTPUT,"already, but I was not able to mount it.\n");
  4491.       CfLog(cfinform,OUTPUT,"");
  4492.       sprintf(OUTPUT,"Check the exports file on host %s? Check for file with same name as dir?\n",host);
  4493.       CfLog(cfinform,OUTPUT,"");
  4494.       }
  4495.  
  4496.    return;
  4497.    }
  4498.  
  4499. if (DONTDO)
  4500.    {
  4501.    printf("%s: add filesystem to %s\n",VPREFIX,VFSTAB[VSYSTEMHARDCLASS]);
  4502.    printf("%s: %s\n",VPREFIX,fstab);
  4503.    }
  4504. else
  4505.    {
  4506.    if ((fp = fopen(VFSTAB[VSYSTEMHARDCLASS],"a")) == NULL)
  4507.       {
  4508.       sprintf(OUTPUT,"Can't open %s for appending\n",VFSTAB[VSYSTEMHARDCLASS]);
  4509.       CfLog(cferror,OUTPUT,"fopen");
  4510.       ReleaseCurrentLock();
  4511.       return;
  4512.       }
  4513.  
  4514.    sprintf(OUTPUT,"Adding filesystem to %s\n",VFSTAB[VSYSTEMHARDCLASS]);
  4515.    CfLog(cfinform,OUTPUT,"");
  4516.    sprintf(OUTPUT,"%s\n",fstab);
  4517.    CfLog(cfinform,OUTPUT,"");
  4518.    fprintf(fp,"%s\n",fstab);
  4519.    fclose(fp);
  4520.    
  4521.    chmod(VFSTAB[VSYSTEMHARDCLASS],DEFAULTSYSTEMMODE);
  4522.    }
  4523. }
  4524.  
  4525.  
  4526. /*******************************************************************/
  4527.  
  4528. CheckFreeSpace (file,kilobytes)
  4529.  
  4530. char *file;
  4531. int kilobytes;
  4532.  
  4533. { struct stat statbuf;
  4534.   int free;
  4535.  
  4536. if (stat(file,&statbuf) == -1)
  4537.    {
  4538.    sprintf(OUTPUT,"Couldn't stat %s checking diskspace\n",file);
  4539.    CfLog(cferror,OUTPUT,"");
  4540.    return true;
  4541.    }
  4542.  
  4543. if (IsMountedFileSystem(&statbuf,file,1)) /* only do this on server */
  4544.    {
  4545.    return true;
  4546.    }
  4547.  
  4548. if (kilobytes < 0)  /* percentage */
  4549.    {
  4550.    free = GetDiskUsage(file,cfpercent);
  4551.    kilobytes = -1 * kilobytes;
  4552.    if (free < kilobytes)
  4553.       {
  4554.       sprintf(OUTPUT,"Free disk space is under %d%% for partition\n",kilobytes);
  4555.       CfLog(cfinform,OUTPUT,"");
  4556.       sprintf(OUTPUT,"containing %s (%d%% free)\n",file,free);
  4557.       CfLog(cfinform,OUTPUT,"");
  4558.       return false;
  4559.       }
  4560.    }
  4561. else
  4562.    {
  4563.    free = GetDiskUsage(file, cfabs);
  4564.  
  4565.    if (free < kilobytes)
  4566.       {
  4567.       sprintf(OUTPUT,"Disk space under %d kB for partition\n",kilobytes);
  4568.       CfLog(cfinform,OUTPUT,"");
  4569.       sprintf(OUTPUT,"containing %s (%d kB free)\n",file,free);
  4570.       CfLog(cfinform,OUTPUT,"");
  4571.       return false;
  4572.       }
  4573.    }
  4574.  
  4575. return true;
  4576. }
  4577.  
  4578. /*******************************************************************/
  4579.  
  4580. AddRequiredClasses(str)
  4581.  
  4582. char *str;
  4583.  
  4584. { char *sp;
  4585.   char currentitem[maxvarsize];
  4586.  
  4587. for (sp = str; *sp != '\0'; sp++)
  4588.    {
  4589.    currentitem[0] = '\0';
  4590.  
  4591.    sscanf(sp,"%[^,:.]",currentitem);
  4592.  
  4593.    sp += strlen(currentitem);
  4594.  
  4595.    AddClassToHeap(currentitem);
  4596.    }
  4597. }
  4598.  
  4599. /*******************************************************************/
  4600.  
  4601. CheckHome(ptr)                      /* iterate check over homedirs */
  4602.  
  4603. struct File *ptr;
  4604.  
  4605. { int RecFileCheck();
  4606.   struct Item *ip1, *ip2;
  4607.   char basename[bufsize],pathbuff[bufsize];
  4608.  
  4609. Debug("CheckHome(%s)\n",ptr->path);
  4610.  
  4611. if (getuid() != 0)                            
  4612.    {
  4613.    printf("%s: Only root can check others' files.\n",VPREFIX);
  4614.    return;
  4615.    }
  4616.  
  4617. if (!MountPathDefined())
  4618.    {
  4619.    return;
  4620.    }
  4621.  
  4622. for (ip1 = VHOMEPATLIST; ip1 != NULL; ip1=ip1->next)
  4623.    {
  4624.    for (ip2 = VMOUNTLIST; ip2 != NULL; ip2=ip2->next)
  4625.       {
  4626.       if (IsExcluded(ip2->classes))
  4627.      {
  4628.      continue;
  4629.      }
  4630.       pathbuff[0]='\0';
  4631.       basename[0]='\0';
  4632.       strcpy(pathbuff,ip2->name);
  4633.       AddSlash(pathbuff);
  4634.       strcat(pathbuff,ip1->name);
  4635.       AddSlash(pathbuff);
  4636.  
  4637.       if (strncmp(ptr->path,"home/",5) == 0) /* home/subdir */
  4638.      {
  4639.      strcat(pathbuff,"*");
  4640.      AddSlash(pathbuff);
  4641.  
  4642.          if (*(ptr->path+4) != '/')
  4643.             {
  4644.             sprintf(OUTPUT,"Illegal use of home in files: %s\n",ptr->path);
  4645.         CfLog(cferror,OUTPUT,"");
  4646.             return;
  4647.             }
  4648.          else
  4649.             {
  4650.             strcat(pathbuff,ptr->path+5);
  4651.             }
  4652.  
  4653.      ExpandWildCardsAndDo(pathbuff,basename,RecFileCheck,ptr);
  4654.      }
  4655.       else
  4656.      {
  4657.      ExpandWildCardsAndDo(pathbuff,basename,RecFileCheck,ptr);
  4658.      }
  4659.       }
  4660.    }
  4661. }
  4662.  
  4663. /*******************************************************************/
  4664.  
  4665.  
  4666. EditItemsInResolvConf(from,list)
  4667.  
  4668. struct Item *from, **list;
  4669.  
  4670. { struct Item *ip;
  4671.   char buf[maxvarsize];
  4672.  
  4673. if (from == NULL)
  4674.    {
  4675.    return;
  4676.    }
  4677. else
  4678.    {
  4679.    EditItemsInResolvConf(from->next,list);
  4680.    if (isdigit(*(from->name)))
  4681.       {
  4682.       sprintf(buf,"nameserver %s",from->name);
  4683.       }
  4684.    else
  4685.       {
  4686.       strcpy(buf,from->name);
  4687.       }
  4688.    
  4689.    DeleteItemStarting(list,buf); /* del+prep = move to head of list */
  4690.    PrependItem(list,buf,NULL);
  4691.    return;
  4692.    }
  4693. }
  4694.  
  4695. /*******************************************************************/
  4696.  
  4697. /* These functions are wrappers for the real functions so that
  4698.     we can abstract the task of parsing general wildcard paths
  4699.     like /a*b/bla?/xyz from a single function ExpandWildCardsAndDo() */
  4700.  
  4701. /*******************************************************************/
  4702.  
  4703. TidyWrapper(startpath,vp)
  4704.  
  4705. char *startpath;
  4706. void *vp;
  4707.  
  4708. { struct Tidy *tp;
  4709.  
  4710. tp = (struct Tidy *) vp;
  4711.  
  4712. Debug2("TidyWrapper(%s)\n",startpath);
  4713.  
  4714. RecursiveTidySpecialArea(startpath,tp,tp->recurse);
  4715. }
  4716.  
  4717. /*******************************************************************/
  4718.  
  4719. RecHomeTidyWrapper(startpath,vp)
  4720.  
  4721. char *startpath;
  4722. void *vp;
  4723.  
  4724. {
  4725. Verbose("Tidying %s...\n",startpath);
  4726. RecursiveHomeTidy(startpath,1,vp);
  4727. }
  4728.  
  4729. /*******************************************************************/
  4730.  
  4731. CheckFileWrapper(startpath,ptr)
  4732.  
  4733. char *startpath;
  4734. struct File *ptr;
  4735.  
  4736. {  struct stat statbuf;
  4737.    mode_t filemode;
  4738.    char *lastnode;
  4739.    int fd;
  4740.  
  4741. if ((strlen(startpath) == 0) || (startpath == NULL))
  4742.    {
  4743.    return;
  4744.    }
  4745.  
  4746. if (ptr->action == touch && IsWildCard(ptr->path))
  4747.    {
  4748.    printf("%s: Can't touch a wildcard! (%s)\n",VPREFIX,ptr->path);
  4749.    return;
  4750.    }
  4751.  
  4752. for (lastnode = startpath+strlen(startpath)-1; *lastnode != '/'; lastnode--)
  4753.    {
  4754.    }
  4755.  
  4756. lastnode++;
  4757.  
  4758. if (ptr->inclusions != NULL && !IsWildItemIn(ptr->inclusions,lastnode))
  4759.    {
  4760.    Debug2("cfengine: skipping non-included pattern %s\n",lastnode);
  4761.  
  4762.    if (stat(startpath,&statbuf) != -1)
  4763.       {
  4764.       if (!S_ISDIR(statbuf.st_mode))
  4765.      {
  4766.      return;  /* assure that we recurse into directories */
  4767.      }
  4768.       }
  4769.    }
  4770.  
  4771. if (IsWildItemIn(ptr->exclusions,lastnode))
  4772.    {
  4773.    Debug2("Skipping excluded pattern file %s\n",lastnode);
  4774.    return;
  4775.    }
  4776.     
  4777. if (stat(startpath,&statbuf) == -1)
  4778.    {
  4779.    Verbose("%s: File/directory <%s> does not exist!\n",VPREFIX,ptr->path);
  4780.  
  4781.    if (TouchDirectory(ptr))                /* files ending in /. */
  4782.       {
  4783.       MakeDirectoriesFor(startpath);
  4784.       ptr->action = fixall;
  4785.       *(startpath+strlen(ptr->path)-2) = '\0';       /* trunc /. */
  4786.       CheckExistingFile(startpath,ptr->plus,ptr->minus,ptr->action,ptr->uid,ptr->gid,&statbuf,ptr,ptr->acl_aliases);
  4787.       return;
  4788.       }
  4789.  
  4790.    filemode = DEFAULTMODE;      /* Decide the mode for filecreation */
  4791.    filemode |=   ptr->plus;
  4792.    filemode &= ~(ptr->minus);
  4793.  
  4794.    switch (ptr->action)
  4795.       {
  4796.       case create:
  4797.       case touch:   if (! DONTDO)
  4798.                        {
  4799.                        MakeDirectoriesFor(startpath);
  4800.                
  4801.                        if ((fd = creat(ptr->path,filemode)) == -1)
  4802.               { 
  4803.               perror("creat");
  4804.               return;
  4805.               }
  4806.                else
  4807.               {
  4808.               close(fd);
  4809.               }
  4810.  
  4811.                CheckExistingFile(startpath,ptr->plus,ptr->minus,fixall,ptr->uid,ptr->gid,&statbuf,ptr,ptr->acl_aliases);
  4812.                        }
  4813.  
  4814.                     sprintf(OUTPUT,"Creating file %s, mode = %o\n",ptr->path,filemode);
  4815.             CfLog(cfinform,OUTPUT,"");
  4816.                     break;
  4817.  
  4818.       case linkchildren: 
  4819.       case warnall:
  4820.       case warnplain:
  4821.       case warndirs:
  4822.       case fixplain:
  4823.       case fixdirs:
  4824.       case fixall:  sprintf(OUTPUT,"File/Dir %s did not exist and was marked (%s)\n",ptr->path,FILEACTIONTEXT[ptr->action]);
  4825.                 CfLog(cfinform,OUTPUT,"");
  4826.                     break;
  4827.  
  4828.       default:      FatalError("cfengine: Internal sofware error: Checkfiles(), bad action\n");
  4829.       }
  4830.    }
  4831. else
  4832.    {
  4833.    if (TouchDirectory(ptr))  /* Don't check just touch */
  4834.       {
  4835.       return;
  4836.       }
  4837.  
  4838.    if (ptr->action == create)
  4839.       {
  4840.       return;
  4841.       }
  4842.  
  4843.    if (ptr->action == linkchildren)
  4844.       {
  4845.       LinkChildren(ptr->path,&statbuf,ptr->uid,ptr->gid,NULL);
  4846.       return;
  4847.       }
  4848.  
  4849.    if (S_ISDIR(statbuf.st_mode) && (ptr->recurse != 0))
  4850.       {
  4851.       if (!IgnoreFile(startpath,ReadLastNode(startpath),ptr->ignores))
  4852.      {
  4853.      Verbose("%s: Skipping ignored root-search directory %s\n",VPREFIX,startpath);
  4854.      CheckExistingFile(startpath,ptr->plus,ptr->minus,ptr->action,ptr->uid,ptr->gid,&statbuf,ptr,ptr->acl_aliases);
  4855.      }
  4856.       RecursiveCheck(startpath,ptr->plus,ptr->minus,ptr->action,ptr->uid,ptr->gid,ptr->recurse,0,ptr); 
  4857.       }
  4858.    else
  4859.       {
  4860.       CheckExistingFile(startpath,ptr->plus,ptr->minus,ptr->action,ptr->uid,ptr->gid,&statbuf,ptr,ptr->acl_aliases);
  4861.       }
  4862.    }
  4863. }
  4864.  
  4865. /*******************************************************************/
  4866.  
  4867. DirectoriesWrapper(dir,ptr)
  4868.  
  4869. char *dir;
  4870. struct File *ptr;
  4871.  
  4872. { struct stat statbuf;
  4873.   char directory[bufsize];
  4874.  
  4875. bzero(directory,bufsize);
  4876. ExpandVarstring(dir,directory,"");
  4877.  
  4878. AddSlash(directory);
  4879. strcat(directory,".");
  4880.  
  4881. MakeDirectoriesFor(directory);
  4882.  
  4883. if (stat(directory,&statbuf) == -1)
  4884.    {
  4885.    sprintf(OUTPUT,"Cannot stat %s\n",directory);
  4886.    CfLog(cfinform,OUTPUT,"stat");
  4887.    return;
  4888.    }
  4889.  
  4890. CheckExistingFile(dir,ptr->plus,ptr->minus,ptr->action,ptr->uid,ptr->gid,&statbuf,ptr,ptr->acl_aliases);
  4891. }
  4892.  
  4893. /*******************************************************************/
  4894.  
  4895. RevertId (uid,gid)
  4896.  
  4897. int uid,gid;
  4898.  
  4899. {
  4900. if (uid != (uid_t)-1)
  4901.    {
  4902.    if (seteuid((uid_t)uid) == -1)
  4903.       {
  4904.       sprintf(OUTPUT,"Unable to regain privileges of user %d\n",uid);
  4905.       CfLog(cferror,OUTPUT,"seteuid");
  4906.       FatalError("Aborting cfengine");
  4907.       }
  4908.    }
  4909.  
  4910. if (gid != (gid_t)-1)
  4911.    {
  4912.    if (setegid((gid_t)gid) == -1)
  4913.       {
  4914.       sprintf(OUTPUT,"Unable to regain privileges of group %d\n",gid);
  4915.       CfLog(cferror,OUTPUT,"seteuid");
  4916.       FatalError("Aborting cfengine");      
  4917.       }
  4918.    }
  4919. }
  4920.  
  4921. /*******************************************************************/
  4922.  
  4923. TZCheck(tzsys,tzlist)
  4924.  
  4925. char *tzsys,*tzlist;
  4926.  
  4927. {
  4928. if ((strncmp(tzsys,"GMT+",4) == 0) || (strncmp(tzsys,"GMT-",4) == 0))
  4929.    {
  4930.    return strncmp(tzsys,tzlist,5); /* e.g. GMT+1 */
  4931.    }
  4932. else
  4933.    {
  4934.    return strncmp(tzsys,tzlist,3); /* e.g. MET or CET */
  4935.    }
  4936. }
  4937.  
  4938. /*******************************************************************/
  4939. /* Level 3                                                         */
  4940. /*******************************************************************/
  4941.  
  4942. ExpandWildCardsAndDo(wildpath,buffer,function,argptr)
  4943.  
  4944. char *wildpath, *buffer;
  4945. int (*function)();
  4946. void *argptr;
  4947.  
  4948.  /* This function recursively expands a path containing wildcards */
  4949.  /* and executes the function pointed to by function for each     */
  4950.  /* matching file or directory                                    */
  4951.  
  4952.  
  4953. { char *rest, extract[bufsize], construct[bufsize],varstring[bufsize], *work;
  4954.   struct stat statbuf;
  4955.   DIR *dirh;
  4956.   struct dirent *dp;
  4957.   int count, isdir = false;
  4958.  
  4959. varstring[0] = '\0';
  4960.  
  4961. ExpandVarstring(wildpath,varstring,NULL);
  4962. work = varstring;
  4963.  
  4964. Debug2("ExpandWildCardsAndDo(%s=%s)\n",wildpath,work);
  4965.  
  4966. extract[0] = '\0';
  4967.  
  4968. if (*work == '/')
  4969.    {
  4970.    work++;
  4971.    isdir = true;
  4972.    }
  4973.  
  4974. sscanf(work,"%[^/]",extract);
  4975. rest = work + strlen(extract);
  4976.  
  4977. if (strlen(extract) == 0)
  4978.    {
  4979.    if (isdir)
  4980.       {
  4981.       strcat(buffer,"/");
  4982.       }
  4983.    (*function)(buffer,argptr);
  4984.    return;
  4985.    }
  4986.  
  4987. if (! IsWildCard(extract))
  4988.    {
  4989.    strcat(buffer,"/");
  4990.    if (BufferOverflow(buffer,extract))
  4991.        {
  4992.        sprintf(OUTPUT,"Culprit %s\n",extract);
  4993.        CfLog(cferror,OUTPUT,"");
  4994.        exit(0);
  4995.        }
  4996.    strcat(buffer,extract);
  4997.    ExpandWildCardsAndDo(rest,buffer,function,argptr);
  4998.    return;
  4999.    }
  5000. else
  5001.    { 
  5002.    strcat(buffer,"/");
  5003.    
  5004.    if ((dirh=opendir(buffer)) == NULL)
  5005.       {
  5006.       sprintf(OUTPUT,"Can't open dir: %s\n",buffer);
  5007.       CfLog(cferror,OUTPUT,"opendir");
  5008.       return;
  5009.       }
  5010.  
  5011.    count = 0;
  5012.    strcpy(construct,buffer);                 /* save relative path */
  5013.  
  5014.    for (dp = readdir(dirh); dp != 0; dp = readdir(dirh))
  5015.       {
  5016.       if (!SensibleFile(dp->d_name,buffer,NULL))
  5017.          {
  5018.          continue;
  5019.          }
  5020.  
  5021.       count++;
  5022.       strcpy(buffer,construct);
  5023.       strcat(buffer,dp->d_name);
  5024.  
  5025.       if (stat(buffer,&statbuf) == -1)
  5026.          {
  5027.          sprintf(OUTPUT,"Can't stat %s\n\n",buffer);
  5028.          CfLog(cferror,OUTPUT,"stat");
  5029.          continue;
  5030.          }
  5031.  
  5032.       if (S_ISDIR(statbuf.st_mode) && WildMatch(extract,dp->d_name))
  5033.          {
  5034.          ExpandWildCardsAndDo(rest,buffer,function,argptr);
  5035.          }
  5036.  
  5037.       }
  5038.  
  5039.    if (count == 0)
  5040.       {
  5041.       sprintf(OUTPUT,"No directories matching %s in %s\n",extract,buffer);
  5042.       CfLog(cfinform,OUTPUT,"");
  5043.       return;
  5044.       }
  5045.    closedir(dirh);
  5046.    }
  5047. }
  5048.  
  5049.  
  5050. /*******************************************************************/
  5051.  
  5052. TouchDirectory(ptr)                     /* True if file path in /. */
  5053.  
  5054. struct File *ptr;
  5055.  
  5056. { char *sp;
  5057.  
  5058. if (ptr->action == touch)
  5059.    {
  5060.    sp = ptr->path+strlen(ptr->path)-2;
  5061.  
  5062.    if (strcmp(sp,"/.") == 0)
  5063.       {
  5064.       return(true);
  5065.       }
  5066.    else
  5067.       {
  5068.       return false;
  5069.       }
  5070.    }
  5071. else
  5072.    {
  5073.    return false;
  5074.    }
  5075. }
  5076.  
  5077.  
  5078. /*******************************************************************/
  5079.  
  5080. RecFileCheck(startpath,ptr)
  5081.  
  5082. char *startpath;
  5083. struct File *ptr;
  5084.  
  5085. {
  5086. Verbose("%s: Checking files in %s...\n",VPREFIX,startpath);
  5087. RecursiveCheck(startpath,ptr->plus,ptr->minus,ptr->action,ptr->uid,ptr->gid,ptr->recurse,0,ptr);
  5088. }
  5089.  
  5090. /*******************************************************************/
  5091.  
  5092. Syntax()
  5093.  
  5094. { int i;
  5095.  
  5096. printf("GNU cfengine: A system configuration tool \n%s\n%s\n",VERSION,COPYRIGHT);
  5097. printf("\n");
  5098. printf("Options:\n\n");
  5099.  
  5100. for (i=0; OPTIONS[i].name != NULL; i++)
  5101.    {
  5102.    printf("--%-20s    (-%c)\n",OPTIONS[i].name,(char)OPTIONS[i].val);
  5103.    }
  5104.  
  5105. printf("\nDebug levels: 1=parsing, 2=running, 3=summary\n");
  5106.  
  5107. printf("\nBug reports to bug-cfengine@gnu.org (News: gnu.cfengine.bug)\n");
  5108. printf("General help to help-cfengine@gnu.org (News: gnu.cfengine.help)\n");
  5109. printf("Info & fixes at http://www.iu.hioslo.no/~mark/cfengine.html\n");
  5110. }
  5111.  
  5112. /*******************************************************************/
  5113. /* Toolkit fstab                                                   */
  5114. /*******************************************************************/
  5115.  
  5116. MatchStringInFstab(str)
  5117.  
  5118. char *str;
  5119.  
  5120. { FILE *fp;
  5121.  
  5122. if ((fp = fopen(VFSTAB[VSYSTEMHARDCLASS],"r")) == NULL)
  5123.    {
  5124.    sprintf(OUTPUT,"Can't open %s for reading\n",VPREFIX,VFSTAB[VSYSTEMHARDCLASS]);
  5125.    CfLog(cferror,OUTPUT,"fopen");
  5126.    return true; /* write nothing */
  5127.    }
  5128.  
  5129. while (!feof(fp))
  5130.    {
  5131.    ReadLine(VBUFF,bufsize,fp);
  5132.  
  5133.    if (VBUFF[0] == '#')
  5134.       {
  5135.       continue;
  5136.       }
  5137.  
  5138.    if (strstr(VBUFF,str))
  5139.       {
  5140.       return true;
  5141.       }
  5142.    }
  5143.  
  5144. fclose(fp);
  5145. return(false);
  5146. }
  5147.  
  5148.  
  5149.  
  5150. /* EOF */
  5151.